package encoder

import (
	
	
	
)

var (
	Marshal   func(interface{}) ([]byte, error)
	Unmarshal func([]byte, interface{}) error
)

type FieldQuery struct {
	Name   string
	Fields []*FieldQuery
	hash   string
}

func ( *FieldQuery) () string {
	if .hash != "" {
		return .hash
	}
	,  := Marshal()
	.hash = string()
	return .hash
}

func ( *FieldQuery) () ([]byte, error) {
	if .Name != "" {
		if len(.Fields) > 0 {
			return Marshal(map[string][]*FieldQuery{.Name: .Fields})
		}
		return Marshal(.Name)
	}
	return Marshal(.Fields)
}

func ( *FieldQuery) () (FieldQueryString, error) {
	,  := Marshal()
	if  != nil {
		return "", 
	}
	return FieldQueryString(), nil
}

type FieldQueryString string

func ( FieldQueryString) () (*FieldQuery, error) {
	var  interface{}
	if  := Unmarshal([]byte(), &);  != nil {
		return nil, 
	}
	return .build(reflect.ValueOf())
}

func ( FieldQueryString) ( reflect.Value) (*FieldQuery, error) {
	switch .Type().Kind() {
	case reflect.String:
		return .buildString()
	case reflect.Map:
		return .buildMap()
	case reflect.Slice:
		return .buildSlice()
	case reflect.Interface:
		return .(reflect.ValueOf(.Interface()))
	}
	return nil, fmt.Errorf("failed to build field query")
}

func ( FieldQueryString) ( reflect.Value) (*FieldQuery, error) {
	 := []byte(.String())
	switch [0] {
	case '[', '{':
		var  interface{}
		if  := Unmarshal(, &);  != nil {
			return nil, 
		}
		if ,  := .(string);  {
			return &FieldQuery{Name: }, nil
		}
		return .build(reflect.ValueOf())
	}
	return &FieldQuery{Name: string()}, nil
}

func ( FieldQueryString) ( reflect.Value) (*FieldQuery, error) {
	 := make([]*FieldQuery, 0, .Len())
	for  := 0;  < .Len(); ++ {
		,  := .build(.Index())
		if  != nil {
			return nil, 
		}
		 = append(, )
	}
	return &FieldQuery{Fields: }, nil
}

func ( FieldQueryString) ( reflect.Value) (*FieldQuery, error) {
	 := .MapKeys()
	if len() != 1 {
		return nil, fmt.Errorf("failed to build field query object")
	}
	 := [0]
	if .Type().Kind() != reflect.String {
		return nil, fmt.Errorf("failed to build field query. invalid object key type")
	}
	 := .String()
	,  := .build(.MapIndex())
	if  != nil {
		return nil, 
	}
	return &FieldQuery{
		Name:   ,
		Fields: .Fields,
	}, nil
}

type queryKey struct{}

func ( context.Context) *FieldQuery {
	 := .Value(queryKey{})
	if  == nil {
		return nil
	}
	,  := .(*FieldQuery)
	if ! {
		return nil
	}
	return 
}

func ( context.Context,  *FieldQuery) context.Context {
	return context.WithValue(, queryKey{}, )
}