package vals

import (
	
)

// Assocer wraps the Assoc method.
type Assocer interface {
	// Assoc returns a slightly modified version of the receiver with key k
	// associated with value v.
	Assoc(k, v interface{}) (interface{}, error)
}

var (
	errAssocUnsupported        = errors.New("assoc is not supported")
	errReplacementMustBeString = errors.New("replacement must be string")
	errAssocWithSlice          = errors.New("assoc with slice not yet supported")
)

// Assoc takes a container, a key and value, and returns a modified version of
// the container, in which the key associated with the value. It is implemented
// for the builtin type string, List and Map types, StructMap types, and types
// satisfying the Assocer interface. For other types, it returns an error.
func (, ,  interface{}) (interface{}, error) {
	switch a := .(type) {
	case string:
		return assocString(, , )
	case List:
		return assocList(, , )
	case Map:
		return .Assoc(, ), nil
	case Assocer:
		return .Assoc(, )
	}
	return nil, errAssocUnsupported
}

func ( string, ,  interface{}) (interface{}, error) {
	, ,  := convertStringIndex(, )
	if  != nil {
		return nil, 
	}
	,  := .(string)
	if ! {
		return nil, errReplacementMustBeString
	}
	return [:] +  + [:], nil
}

func ( List, ,  interface{}) (interface{}, error) {
	,  := ConvertListIndex(, .Len())
	if  != nil {
		return nil, 
	}
	if .Slice {
		return nil, errAssocWithSlice
	}
	return .Assoc(.Lower, ), nil
}