// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package schema

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"sync"

	"github.com/hashicorp/terraform/internal/legacy/terraform"
	"github.com/mitchellh/mapstructure"
)

// ConfigFieldReader reads fields out of an untyped map[string]string to the
// best of its ability. It also applies defaults from the Schema. (The other
// field readers do not need default handling because they source fully
// populated data structures.)
type ConfigFieldReader struct {
	Config *terraform.ResourceConfig
	Schema map[string]*Schema

	indexMaps map[string]map[string]int
	once      sync.Once
}

func (r *ConfigFieldReader) ReadField(address []string) (FieldReadResult, error) {
	r.once.Do(func() { r.indexMaps = make(map[string]map[string]int) })
	return r.readField(address, false)
}

func (r *ConfigFieldReader) readField(
	address []string, nested bool) (FieldReadResult, error) {
	schemaList := addrToSchema(address, r.Schema)
	if len(schemaList) == 0 {
		return FieldReadResult{}, nil
	}

	if !nested {
		// If we have a set anywhere in the address, then we need to
		// read that set out in order and actually replace that part of
		// the address with the real list index. i.e. set.50 might actually
		// map to set.12 in the config, since it is in list order in the
		// config, not indexed by set value.
		for i, v := range schemaList {
			// Sets are the only thing that cause this issue.
			if v.Type != TypeSet {
				continue
			}

			// If we're at the end of the list, then we don't have to worry
			// about this because we're just requesting the whole set.
			if i == len(schemaList)-1 {
				continue
			}

			// If we're looking for the count, then ignore...
			if address[i+1] == "#" {
				continue
			}

			indexMap, ok := r.indexMaps[strings.Join(address[:i+1], ".")]
			if !ok {
				// Get the set so we can get the index map that tells us the
				// mapping of the hash code to the list index
				_, err := r.readSet(address[:i+1], v)
				if err != nil {
					return FieldReadResult{}, err
				}
				indexMap = r.indexMaps[strings.Join(address[:i+1], ".")]
			}

			index, ok := indexMap[address[i+1]]
			if !ok {
				return FieldReadResult{}, nil
			}

			address[i+1] = strconv.FormatInt(int64(index), 10)
		}
	}

	k := strings.Join(address, ".")
	schema := schemaList[len(schemaList)-1]

	// If we're getting the single element of a promoted list, then
	// check to see if we have a single element we need to promote.
	if address[len(address)-1] == "0" && len(schemaList) > 1 {
		lastSchema := schemaList[len(schemaList)-2]
		if lastSchema.Type == TypeList && lastSchema.PromoteSingle {
			k := strings.Join(address[:len(address)-1], ".")
			result, err := r.readPrimitive(k, schema)
			if err == nil {
				return result, nil
			}
		}
	}

	if protoVersion5 {
		switch schema.Type {
		case TypeList, TypeSet, TypeMap, typeObject:
			// Check if the value itself is unknown.
			// The new protocol shims will add unknown values to this list of
			// ComputedKeys. This is the only way we have to indicate that a
			// collection is unknown in the config
			for _, unknown := range r.Config.ComputedKeys {
				if k == unknown {
					log.Printf("[DEBUG] setting computed for %q from ComputedKeys", k)
					return FieldReadResult{Computed: true, Exists: true}, nil
				}
			}
		}
	}

	switch schema.Type {
	case TypeBool, TypeFloat, TypeInt, TypeString:
		return r.readPrimitive(k, schema)
	case TypeList:
		// If we support promotion then we first check if we have a lone
		// value that we must promote.
		// a value that is alone.
		if schema.PromoteSingle {
			result, err := r.readPrimitive(k, schema.Elem.(*Schema))
			if err == nil && result.Exists {
				result.Value = []interface{}{result.Value}
				return result, nil
			}
		}

		return readListField(&nestedConfigFieldReader{r}, address, schema)
	case TypeMap:
		return r.readMap(k, schema)
	case TypeSet:
		return r.readSet(address, schema)
	case typeObject:
		return readObjectField(
			&nestedConfigFieldReader{r},
			address, schema.Elem.(map[string]*Schema))
	default:
		panic(fmt.Sprintf("Unknown type: %s", schema.Type))
	}
}

func (r *ConfigFieldReader) readMap(k string, schema *Schema) (FieldReadResult, error) {
	// We want both the raw value and the interpolated. We use the interpolated
	// to store actual values and we use the raw one to check for
	// computed keys. Actual values are obtained in the switch, depending on
	// the type of the raw value.
	mraw, ok := r.Config.GetRaw(k)
	if !ok {
		// check if this is from an interpolated field by seeing if it exists
		// in the config
		_, ok := r.Config.Get(k)
		if !ok {
			// this really doesn't exist
			return FieldReadResult{}, nil
		}

		// We couldn't fetch the value from a nested data structure, so treat the
		// raw value as an interpolation string. The mraw value is only used
		// for the type switch below.
		mraw = "${INTERPOLATED}"
	}

	result := make(map[string]interface{})
	computed := false
	switch m := mraw.(type) {
	case string:
		// This is a map which has come out of an interpolated variable, so we
		// can just get the value directly from config. Values cannot be computed
		// currently.
		v, _ := r.Config.Get(k)

		// If this isn't a map[string]interface, it must be computed.
		mapV, ok := v.(map[string]interface{})
		if !ok {
			return FieldReadResult{
				Exists:   true,
				Computed: true,
			}, nil
		}

		// Otherwise we can proceed as usual.
		for i, iv := range mapV {
			result[i] = iv
		}
	case []interface{}:
		for i, innerRaw := range m {
			for ik := range innerRaw.(map[string]interface{}) {
				key := fmt.Sprintf("%s.%d.%s", k, i, ik)
				if r.Config.IsComputed(key) {
					computed = true
					break
				}

				v, _ := r.Config.Get(key)
				result[ik] = v
			}
		}
	case []map[string]interface{}:
		for i, innerRaw := range m {
			for ik := range innerRaw {
				key := fmt.Sprintf("%s.%d.%s", k, i, ik)
				if r.Config.IsComputed(key) {
					computed = true
					break
				}

				v, _ := r.Config.Get(key)
				result[ik] = v
			}
		}
	case map[string]interface{}:
		for ik := range m {
			key := fmt.Sprintf("%s.%s", k, ik)
			if r.Config.IsComputed(key) {
				computed = true
				break
			}

			v, _ := r.Config.Get(key)
			result[ik] = v
		}
	case nil:
		// the map may have been empty on the configuration, so we leave the
		// empty result
	default:
		panic(fmt.Sprintf("unknown type: %#v", mraw))
	}

	err := mapValuesToPrimitive(k, result, schema)
	if err != nil {
		return FieldReadResult{}, nil
	}

	var value interface{}
	if !computed {
		value = result
	}

	return FieldReadResult{
		Value:    value,
		Exists:   true,
		Computed: computed,
	}, nil
}

func (r *ConfigFieldReader) readPrimitive(
	k string, schema *Schema) (FieldReadResult, error) {
	raw, ok := r.Config.Get(k)
	if !ok {
		// Nothing in config, but we might still have a default from the schema
		var err error
		raw, err = schema.DefaultValue()
		if err != nil {
			return FieldReadResult{}, fmt.Errorf("%s, error loading default: %s", k, err)
		}

		if raw == nil {
			return FieldReadResult{}, nil
		}
	}

	var result string
	if err := mapstructure.WeakDecode(raw, &result); err != nil {
		return FieldReadResult{}, err
	}

	computed := r.Config.IsComputed(k)
	returnVal, err := stringToPrimitive(result, computed, schema)
	if err != nil {
		return FieldReadResult{}, err
	}

	return FieldReadResult{
		Value:    returnVal,
		Exists:   true,
		Computed: computed,
	}, nil
}

func (r *ConfigFieldReader) readSet(
	address []string, schema *Schema) (FieldReadResult, error) {
	indexMap := make(map[string]int)
	// Create the set that will be our result
	set := schema.ZeroValue().(*Set)

	raw, err := readListField(&nestedConfigFieldReader{r}, address, schema)
	if err != nil {
		return FieldReadResult{}, err
	}
	if !raw.Exists {
		return FieldReadResult{Value: set}, nil
	}

	// If the list is computed, the set is necessarilly computed
	if raw.Computed {
		return FieldReadResult{
			Value:    set,
			Exists:   true,
			Computed: raw.Computed,
		}, nil
	}

	// Build up the set from the list elements
	for i, v := range raw.Value.([]interface{}) {
		// Check if any of the keys in this item are computed
		computed := r.hasComputedSubKeys(
			fmt.Sprintf("%s.%d", strings.Join(address, "."), i), schema)

		code := set.add(v, computed)
		indexMap[code] = i
	}

	r.indexMaps[strings.Join(address, ".")] = indexMap

	return FieldReadResult{
		Value:  set,
		Exists: true,
	}, nil
}

// hasComputedSubKeys walks through a schema and returns whether or not the
// given key contains any subkeys that are computed.
func (r *ConfigFieldReader) hasComputedSubKeys(key string, schema *Schema) bool {
	prefix := key + "."

	switch t := schema.Elem.(type) {
	case *Resource:
		for k, schema := range t.Schema {
			if r.Config.IsComputed(prefix + k) {
				return true
			}

			if r.hasComputedSubKeys(prefix+k, schema) {
				return true
			}
		}
	}

	return false
}

// nestedConfigFieldReader is a funny little thing that just wraps a
// ConfigFieldReader to call readField when ReadField is called so that
// we don't recalculate the set rewrites in the address, which leads to
// an infinite loop.
type nestedConfigFieldReader struct {
	Reader *ConfigFieldReader
}

func (r *nestedConfigFieldReader) ReadField(
	address []string) (FieldReadResult, error) {
	return r.Reader.readField(address, true)
}
