package hcl

import (
	"errors"
	"fmt"
	"reflect"
	"sort"
	"strconv"
	"strings"

	"github.com/hashicorp/hcl/hcl/ast"
	"github.com/hashicorp/hcl/hcl/parser"
	"github.com/hashicorp/hcl/hcl/token"
)

// This is the tag to use with structures to have settings for HCL
const tagName = "hcl"

var (
	// nodeType holds a reference to the type of ast.Node
	nodeType reflect.Type = findNodeType()
)

// Unmarshal accepts a byte slice as input and writes the
// data to the value pointed to by v.
func Unmarshal(bs []byte, v interface{}) error {
	root, err := parse(bs)
	if err != nil {
		return err
	}

	return DecodeObject(v, root)
}

// Decode reads the given input and decodes it into the structure
// given by `out`.
func Decode(out interface{}, in string) error {
	obj, err := Parse(in)
	if err != nil {
		return err
	}

	return DecodeObject(out, obj)
}

// DecodeObject is a lower-level version of Decode. It decodes a
// raw Object into the given output.
func DecodeObject(out interface{}, n ast.Node) error {
	val := reflect.ValueOf(out)
	if val.Kind() != reflect.Ptr {
		return errors.New("result must be a pointer")
	}

	// If we have the file, we really decode the root node
	if f, ok := n.(*ast.File); ok {
		n = f.Node
	}

	var d decoder
	return d.decode("root", n, val.Elem())
}

type decoder struct {
	stack []reflect.Kind
}

func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
	k := result

	// If we have an interface with a valid value, we use that
	// for the check.
	if result.Kind() == reflect.Interface {
		elem := result.Elem()
		if elem.IsValid() {
			k = elem
		}
	}

	// Push current onto stack unless it is an interface.
	if k.Kind() != reflect.Interface {
		d.stack = append(d.stack, k.Kind())

		// Schedule a pop
		defer func() {
			d.stack = d.stack[:len(d.stack)-1]
		}()
	}

	switch k.Kind() {
	case reflect.Bool:
		return d.decodeBool(name, node, result)
	case reflect.Float32, reflect.Float64:
		return d.decodeFloat(name, node, result)
	case reflect.Int, reflect.Int32, reflect.Int64:
		return d.decodeInt(name, node, result)
	case reflect.Interface:
		// When we see an interface, we make our own thing
		return d.decodeInterface(name, node, result)
	case reflect.Map:
		return d.decodeMap(name, node, result)
	case reflect.Ptr:
		return d.decodePtr(name, node, result)
	case reflect.Slice:
		return d.decodeSlice(name, node, result)
	case reflect.String:
		return d.decodeString(name, node, result)
	case reflect.Struct:
		return d.decodeStruct(name, node, result)
	default:
		return &parser.PosError{
			Pos: node.Pos(),
			Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
		}
	}
}

func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error {
	switch n := node.(type) {
	case *ast.LiteralType:
		if n.Token.Type == token.BOOL {
			v, err := strconv.ParseBool(n.Token.Text)
			if err != nil {
				return err
			}

			result.Set(reflect.ValueOf(v))
			return nil
		}
	}

	return &parser.PosError{
		Pos: node.Pos(),
		Err: fmt.Errorf("%s: unknown type %T", name, node),
	}
}

func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
	switch n := node.(type) {
	case *ast.LiteralType:
		if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER {
			v, err := strconv.ParseFloat(n.Token.Text, 64)
			if err != nil {
				return err
			}

			result.Set(reflect.ValueOf(v).Convert(result.Type()))
			return nil
		}
	}

	return &parser.PosError{
		Pos: node.Pos(),
		Err: fmt.Errorf("%s: unknown type %T", name, node),
	}
}

func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error {
	switch n := node.(type) {
	case *ast.LiteralType:
		switch n.Token.Type {
		case token.NUMBER:
			v, err := strconv.ParseInt(n.Token.Text, 0, 0)
			if err != nil {
				return err
			}

			if result.Kind() == reflect.Interface {
				result.Set(reflect.ValueOf(int(v)))
			} else {
				result.SetInt(v)
			}
			return nil
		case token.STRING:
			v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
			if err != nil {
				return err
			}

			if result.Kind() == reflect.Interface {
				result.Set(reflect.ValueOf(int(v)))
			} else {
				result.SetInt(v)
			}
			return nil
		}
	}

	return &parser.PosError{
		Pos: node.Pos(),
		Err: fmt.Errorf("%s: unknown type %T", name, node),
	}
}

func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error {
	// When we see an ast.Node, we retain the value to enable deferred decoding.
	// Very useful in situations where we want to preserve ast.Node information
	// like Pos
	if result.Type() == nodeType && result.CanSet() {
		result.Set(reflect.ValueOf(node))
		return nil
	}

	var set reflect.Value
	redecode := true

	// For testing types, ObjectType should just be treated as a list. We
	// set this to a temporary var because we want to pass in the real node.
	testNode := node
	if ot, ok := node.(*ast.ObjectType); ok {
		testNode = ot.List
	}

	switch n := testNode.(type) {
	case *ast.ObjectList:
		// If we're at the root or we're directly within a slice, then we
		// decode objects into map[string]interface{}, otherwise we decode
		// them into lists.
		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
			var temp map[string]interface{}
			tempVal := reflect.ValueOf(temp)
			result := reflect.MakeMap(
				reflect.MapOf(
					reflect.TypeOf(""),
					tempVal.Type().Elem()))

			set = result
		} else {
			var temp []map[string]interface{}
			tempVal := reflect.ValueOf(temp)
			result := reflect.MakeSlice(
				reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items))
			set = result
		}
	case *ast.ObjectType:
		// If we're at the root or we're directly within a slice, then we
		// decode objects into map[string]interface{}, otherwise we decode
		// them into lists.
		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
			var temp map[string]interface{}
			tempVal := reflect.ValueOf(temp)
			result := reflect.MakeMap(
				reflect.MapOf(
					reflect.TypeOf(""),
					tempVal.Type().Elem()))

			set = result
		} else {
			var temp []map[string]interface{}
			tempVal := reflect.ValueOf(temp)
			result := reflect.MakeSlice(
				reflect.SliceOf(tempVal.Type().Elem()), 0, 1)
			set = result
		}
	case *ast.ListType:
		var temp []interface{}
		tempVal := reflect.ValueOf(temp)
		result := reflect.MakeSlice(
			reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
		set = result
	case *ast.LiteralType:
		switch n.Token.Type {
		case token.BOOL:
			var result bool
			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
		case token.FLOAT:
			var result float64
			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
		case token.NUMBER:
			var result int
			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
		case token.STRING, token.HEREDOC:
			set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
		default:
			return &parser.PosError{
				Pos: node.Pos(),
				Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node),
			}
		}
	default:
		return fmt.Errorf(
			"%s: cannot decode into interface: %T",
			name, node)
	}

	// Set the result to what its supposed to be, then reset
	// result so we don't reflect into this method anymore.
	result.Set(set)

	if redecode {
		// Revisit the node so that we can use the newly instantiated
		// thing and populate it.
		if err := d.decode(name, node, result); err != nil {
			return err
		}
	}

	return nil
}

func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error {
	if item, ok := node.(*ast.ObjectItem); ok {
		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
	}

	if ot, ok := node.(*ast.ObjectType); ok {
		node = ot.List
	}

	n, ok := node.(*ast.ObjectList)
	if !ok {
		return &parser.PosError{
			Pos: node.Pos(),
			Err: fmt.Errorf("%s: not an object type for map (%T)", name, node),
		}
	}

	// If we have an interface, then we can address the interface,
	// but not the slice itself, so get the element but set the interface
	set := result
	if result.Kind() == reflect.Interface {
		result = result.Elem()
	}

	resultType := result.Type()
	resultElemType := resultType.Elem()
	resultKeyType := resultType.Key()
	if resultKeyType.Kind() != reflect.String {
		return &parser.PosError{
			Pos: node.Pos(),
			Err: fmt.Errorf("%s: map must have string keys", name),
		}
	}

	// Make a map if it is nil
	resultMap := result
	if result.IsNil() {
		resultMap = reflect.MakeMap(
			reflect.MapOf(resultKeyType, resultElemType))
	}

	// Go through each element and decode it.
	done := make(map[string]struct{})
	for _, item := range n.Items {
		if item.Val == nil {
			continue
		}

		// github.com/hashicorp/terraform/issue/5740
		if len(item.Keys) == 0 {
			return &parser.PosError{
				Pos: node.Pos(),
				Err: fmt.Errorf("%s: map must have string keys", name),
			}
		}

		// Get the key we're dealing with, which is the first item
		keyStr := item.Keys[0].Token.Value().(string)

		// If we've already processed this key, then ignore it
		if _, ok := done[keyStr]; ok {
			continue
		}

		// Determine the value. If we have more than one key, then we
		// get the objectlist of only these keys.
		itemVal := item.Val
		if len(item.Keys) > 1 {
			itemVal = n.Filter(keyStr)
			done[keyStr] = struct{}{}
		}

		// Make the field name
		fieldName := fmt.Sprintf("%s.%s", name, keyStr)

		// Get the key/value as reflection values
		key := reflect.ValueOf(keyStr)
		val := reflect.Indirect(reflect.New(resultElemType))

		// If we have a pre-existing value in the map, use that
		oldVal := resultMap.MapIndex(key)
		if oldVal.IsValid() {
			val.Set(oldVal)
		}

		// Decode!
		if err := d.decode(fieldName, itemVal, val); err != nil {
			return err
		}

		// Set the value on the map
		resultMap.SetMapIndex(key, val)
	}

	// Set the final map if we can
	set.Set(resultMap)
	return nil
}

func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error {
	// Create an element of the concrete (non pointer) type and decode
	// into that. Then set the value of the pointer to this type.
	resultType := result.Type()
	resultElemType := resultType.Elem()
	val := reflect.New(resultElemType)
	if err := d.decode(name, node, reflect.Indirect(val)); err != nil {
		return err
	}

	result.Set(val)
	return nil
}

func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error {
	// If we have an interface, then we can address the interface,
	// but not the slice itself, so get the element but set the interface
	set := result
	if result.Kind() == reflect.Interface {
		result = result.Elem()
	}
	// Create the slice if it isn't nil
	resultType := result.Type()
	resultElemType := resultType.Elem()
	if result.IsNil() {
		resultSliceType := reflect.SliceOf(resultElemType)
		result = reflect.MakeSlice(
			resultSliceType, 0, 0)
	}

	// Figure out the items we'll be copying into the slice
	var items []ast.Node
	switch n := node.(type) {
	case *ast.ObjectList:
		items = make([]ast.Node, len(n.Items))
		for i, item := range n.Items {
			items[i] = item
		}
	case *ast.ObjectType:
		items = []ast.Node{n}
	case *ast.ListType:
		items = n.List
	default:
		return &parser.PosError{
			Pos: node.Pos(),
			Err: fmt.Errorf("unknown slice type: %T", node),
		}
	}

	for i, item := range items {
		fieldName := fmt.Sprintf("%s[%d]", name, i)

		// Decode
		val := reflect.Indirect(reflect.New(resultElemType))

		// if item is an object that was decoded from ambiguous JSON and
		// flattened, make sure it's expanded if it needs to decode into a
		// defined structure.
		item := expandObject(item, val)

		if err := d.decode(fieldName, item, val); err != nil {
			return err
		}

		// Append it onto the slice
		result = reflect.Append(result, val)
	}

	set.Set(result)
	return nil
}

// expandObject detects if an ambiguous JSON object was flattened to a List which
// should be decoded into a struct, and expands the ast to properly deocode.
func expandObject(node ast.Node, result reflect.Value) ast.Node {
	item, ok := node.(*ast.ObjectItem)
	if !ok {
		return node
	}

	elemType := result.Type()

	// our target type must be a struct
	switch elemType.Kind() {
	case reflect.Ptr:
		switch elemType.Elem().Kind() {
		case reflect.Struct:
			//OK
		default:
			return node
		}
	case reflect.Struct:
		//OK
	default:
		return node
	}

	// A list value will have a key and field name. If it had more fields,
	// it wouldn't have been flattened.
	if len(item.Keys) != 2 {
		return node
	}

	keyToken := item.Keys[0].Token
	item.Keys = item.Keys[1:]

	// we need to un-flatten the ast enough to decode
	newNode := &ast.ObjectItem{
		Keys: []*ast.ObjectKey{
			&ast.ObjectKey{
				Token: keyToken,
			},
		},
		Val: &ast.ObjectType{
			List: &ast.ObjectList{
				Items: []*ast.ObjectItem{item},
			},
		},
	}

	return newNode
}

func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error {
	switch n := node.(type) {
	case *ast.LiteralType:
		switch n.Token.Type {
		case token.NUMBER:
			result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type()))
			return nil
		case token.STRING, token.HEREDOC:
			result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type()))
			return nil
		}
	}

	return &parser.PosError{
		Pos: node.Pos(),
		Err: fmt.Errorf("%s: unknown type for string %T", name, node),
	}
}

func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error {
	var item *ast.ObjectItem
	if it, ok := node.(*ast.ObjectItem); ok {
		item = it
		node = it.Val
	}

	if ot, ok := node.(*ast.ObjectType); ok {
		node = ot.List
	}

	// Handle the special case where the object itself is a literal. Previously
	// the yacc parser would always ensure top-level elements were arrays. The new
	// parser does not make the same guarantees, thus we need to convert any
	// top-level literal elements into a list.
	if _, ok := node.(*ast.LiteralType); ok && item != nil {
		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
	}

	list, ok := node.(*ast.ObjectList)
	if !ok {
		return &parser.PosError{
			Pos: node.Pos(),
			Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node),
		}
	}

	// This slice will keep track of all the structs we'll be decoding.
	// There can be more than one struct if there are embedded structs
	// that are squashed.
	structs := make([]reflect.Value, 1, 5)
	structs[0] = result

	// Compile the list of all the fields that we're going to be decoding
	// from all the structs.
	fields := make(map[*reflect.StructField]reflect.Value)
	for len(structs) > 0 {
		structVal := structs[0]
		structs = structs[1:]

		structType := structVal.Type()
		for i := 0; i < structType.NumField(); i++ {
			fieldType := structType.Field(i)
			tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")

			// Ignore fields with tag name "-"
			if tagParts[0] == "-" {
				continue
			}

			if fieldType.Anonymous {
				fieldKind := fieldType.Type.Kind()
				if fieldKind != reflect.Struct {
					return &parser.PosError{
						Pos: node.Pos(),
						Err: fmt.Errorf("%s: unsupported type to struct: %s",
							fieldType.Name, fieldKind),
					}
				}

				// We have an embedded field. We "squash" the fields down
				// if specified in the tag.
				squash := false
				for _, tag := range tagParts[1:] {
					if tag == "squash" {
						squash = true
						break
					}
				}

				if squash {
					structs = append(
						structs, result.FieldByName(fieldType.Name))
					continue
				}
			}

			// Normal struct field, store it away
			fields[&fieldType] = structVal.Field(i)
		}
	}

	usedKeys := make(map[string]struct{})
	decodedFields := make([]string, 0, len(fields))
	decodedFieldsVal := make([]reflect.Value, 0)
	unusedKeysVal := make([]reflect.Value, 0)
	for fieldType, field := range fields {
		if !field.IsValid() {
			// This should never happen
			panic("field is not valid")
		}

		// If we can't set the field, then it is unexported or something,
		// and we just continue onwards.
		if !field.CanSet() {
			continue
		}

		fieldName := fieldType.Name

		tagValue := fieldType.Tag.Get(tagName)
		tagParts := strings.SplitN(tagValue, ",", 2)
		if len(tagParts) >= 2 {
			switch tagParts[1] {
			case "decodedFields":
				decodedFieldsVal = append(decodedFieldsVal, field)
				continue
			case "key":
				if item == nil {
					return &parser.PosError{
						Pos: node.Pos(),
						Err: fmt.Errorf("%s: %s asked for 'key', impossible",
							name, fieldName),
					}
				}

				field.SetString(item.Keys[0].Token.Value().(string))
				continue
			case "unusedKeys":
				unusedKeysVal = append(unusedKeysVal, field)
				continue
			}
		}

		if tagParts[0] != "" {
			fieldName = tagParts[0]
		}

		// Determine the element we'll use to decode. If it is a single
		// match (only object with the field), then we decode it exactly.
		// If it is a prefix match, then we decode the matches.
		filter := list.Filter(fieldName)

		prefixMatches := filter.Children()
		matches := filter.Elem()
		if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
			continue
		}

		// Track the used key
		usedKeys[fieldName] = struct{}{}

		// Create the field name and decode. We range over the elements
		// because we actually want the value.
		fieldName = fmt.Sprintf("%s.%s", name, fieldName)
		if len(prefixMatches.Items) > 0 {
			if err := d.decode(fieldName, prefixMatches, field); err != nil {
				return err
			}
		}
		for _, match := range matches.Items {
			var decodeNode ast.Node = match.Val
			if ot, ok := decodeNode.(*ast.ObjectType); ok {
				decodeNode = &ast.ObjectList{Items: ot.List.Items}
			}

			if err := d.decode(fieldName, decodeNode, field); err != nil {
				return err
			}
		}

		decodedFields = append(decodedFields, fieldType.Name)
	}

	if len(decodedFieldsVal) > 0 {
		// Sort it so that it is deterministic
		sort.Strings(decodedFields)

		for _, v := range decodedFieldsVal {
			v.Set(reflect.ValueOf(decodedFields))
		}
	}

	return nil
}

// findNodeType returns the type of ast.Node
func findNodeType() reflect.Type {
	var nodeContainer struct {
		Node ast.Node
	}
	value := reflect.ValueOf(nodeContainer).FieldByName("Node")
	return value.Type()
}
