// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of The BSD 3-Clause License
// that can be found in the LICENSE file.

package uritemplate

import 

// A varname containing pct-encoded characters is not the same variable as
// a varname with those same characters decoded.
//
// -- https://tools.ietf.org/html/rfc6570#section-2.3
type Values map[string]Value

func ( Values) ( string,  Value) {
	[] = 
}

func ( Values) ( string) Value {
	if  == nil {
		return Value{}
	}
	return []
}

type ValueType uint8

const (
	ValueTypeString = iota
	ValueTypeList
	ValueTypeKV
	valueTypeLast
)

var valueTypeNames = []string{
	"String",
	"List",
	"KV",
}

func ( ValueType) () string {
	if  < valueTypeLast {
		return valueTypeNames[]
	}
	return ""
}

type Value struct {
	T ValueType
	V []string
}

func ( Value) () string {
	if .Valid() && .T == ValueTypeString {
		return .V[0]
	}
	return ""
}

func ( Value) () []string {
	if .Valid() && .T == ValueTypeList {
		return .V
	}
	return nil
}

func ( Value) () []string {
	if .Valid() && .T == ValueTypeKV {
		return .V
	}
	return nil
}

func ( Value) () bool {
	switch .T {
	default:
		return false
	case ValueTypeString:
		return len(.V) > 0
	case ValueTypeList:
		return len(.V) > 0
	case ValueTypeKV:
		return len(.V) > 0 && len(.V)%2 == 0
	}
}

func ( Value) ( *strings.Builder,  varspec,  *expression) error {
	switch .T {
	case ValueTypeString:
		 := .V[0]
		var  int
		if  := len(); .maxlen < 1 || .maxlen >  {
			 = 
		} else {
			 = .maxlen
		}

		if .named {
			.WriteString(.name)
			if  == "" {
				.WriteString(.ifemp)
				return nil
			}
			.WriteByte('=')
		}
		return .escape(, [:])
	case ValueTypeList:
		var  string
		if .explode {
			 = .sep
		} else {
			 = ","
		}

		var  string
		var  string
		if .explode && .named {
			 = .name + "="
			 = .name + .ifemp
		}

		if !.explode && .named {
			.WriteString(.name)
			.WriteByte('=')
		}
		for  := range .V {
			 := .V[]
			if  > 0 {
				.WriteString()
			}
			if  == "" {
				.WriteString()
				continue
			}
			.WriteString()

			if  := .escape(, );  != nil {
				return 
			}
		}
	case ValueTypeKV:
		var  string
		var  string
		if .explode {
			 = .sep
			 = "="
		} else {
			 = ","
			 = ","
		}

		var  string
		var  escapeFunc
		if .explode && .named {
			 = .ifemp
			 = escapeLiteral
		} else {
			 = ","
			 = .escape
		}

		if !.explode && .named {
			.WriteString(.name)
			.WriteByte('=')
		}

		for  := 0;  < len(.V);  += 2 {
			if  > 0 {
				.WriteString()
			}
			if  := (, .V[]);  != nil {
				return 
			}
			if .V[+1] == "" {
				.WriteString()
				continue
			}
			.WriteString()

			if  := .escape(, .V[+1]);  != nil {
				return 
			}
		}
	}
	return nil
}

// String returns Value that represents string.
func ( string) Value {
	return Value{
		T: ValueTypeString,
		V: []string{},
	}
}

// List returns Value that represents list.
func ( ...string) Value {
	return Value{
		T: ValueTypeList,
		V: ,
	}
}

// KV returns Value that represents associative list.
// KV panics if len(kv) is not even.
func ( ...string) Value {
	if len()%2 != 0 {
		panic("uritemplate.go: count of the kv must be even number")
	}
	return Value{
		T: ValueTypeKV,
		V: ,
	}
}