package httpsfv

import (
	
	
)

// Params are an ordered map of key-value pairs that are associated with an item or an inner list.
//
// See https://httpwg.org/specs/rfc9651.html#param.
type Params struct {
	names  []string
	values map[string]interface{}
}

// ErrInvalidParameterFormat is returned when the format of a parameter is invalid.
var ErrInvalidParameterFormat = errors.New("invalid parameter format")

// ErrInvalidParameterValue is returned when a parameter key is invalid.
var ErrInvalidParameterValue = errors.New("invalid parameter value")

// ErrMissingParameters is returned when the Params structure is missing from the element.
var ErrMissingParameters = errors.New("missing parameters")

// NewParams creates a new ordered map.
func () *Params {
	 := Params{}
	.names = []string{}
	.values = map[string]interface{}{}

	return &
}

// Get retrieves a parameter.
func ( *Params) ( string) (interface{}, bool) {
	,  := .values[]

	return , 
}

// Add appends a new parameter to the ordered list.
// If the key already exists, overwrite its value.
func ( *Params) ( string,  interface{}) {
	assertBareItem()

	if ,  := .values[]; ! {
		.names = append(.names, )
	}

	.values[] = 
}

// Del removes a parameter from the ordered list.
func ( *Params) ( string) bool {
	if ,  := .values[]; ! {
		return false
	}

	for ,  := range .names {
		if  ==  {
			.names = append(.names[:], .names[+1:]...)

			break
		}
	}

	delete(.values, )

	return true
}

// Names retrieves the list of parameter names in the appropriate order.
func ( *Params) () []string {
	return .names
}

// marshalSFV serializes as defined in
// https://httpwg.org/specs/rfc9651.html#ser-params.
func ( *Params) ( *strings.Builder) error {
	if  == nil {
		return ErrMissingParameters
	}
	for ,  := range .names {
		if  := .WriteByte(';');  != nil {
			return 
		}

		if  := marshalKey(, );  != nil {
			return 
		}

		 := .values[]
		if  == true {
			continue
		}

		if  := .WriteByte('=');  != nil {
			return 
		}

		if  := marshalBareItem(, );  != nil {
			return 
		}
	}

	return nil
}

// parseParams parses as defined in
// https://httpwg.org/specs/rfc9651.html#parse-param.
func parseParams( *scanner) (*Params, error) {
	 := NewParams()

	for !.eof() {
		if .data[.off] != ';' {
			break
		}
		.off++
		.scanWhileSp()

		,  := parseKey()
		if  != nil {
			return nil, 
		}

		var  interface{}

		if !.eof() && .data[.off] == '=' {
			.off++

			,  = parseBareItem()
			if  != nil {
				return nil, 
			}
		} else {
			 = true
		}

		.Add(, )
	}

	return , nil
}