package hcl2shim

import (
	"fmt"
	"math/big"

	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/internal/configs/configschema"
)

// UnknownVariableValue is a sentinel value that can be used
// to denote that the value of a variable is unknown at this time.
// RawConfig uses this information to build up data about
// unknown keys.
const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66"

// ConfigValueFromHCL2Block is like ConfigValueFromHCL2 but it works only for
// known object values and uses the provided block schema to perform some
// additional normalization to better mimic the shape of value that the old
// HCL1/HIL-based codepaths would've produced.
//
// In particular, it discards the collections that we use to represent nested
// blocks (other than NestingSingle) if they are empty, which better mimics
// the HCL1 behavior because HCL1 had no knowledge of the schema and so didn't
// know that an unspecified block _could_ exist.
//
// The given object value must conform to the schema's implied type or this
// function will panic or produce incorrect results.
//
// This is primarily useful for the final transition from new-style values to
// terraform.ResourceConfig before calling to a legacy provider, since
// helper/schema (the old provider SDK) is particularly sensitive to these
// subtle differences within its validation code.
func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[string]interface{} {
	if v.IsNull() {
		return nil
	}
	if !v.IsKnown() {
		panic("ConfigValueFromHCL2Block used with unknown value")
	}
	if !v.Type().IsObjectType() {
		panic(fmt.Sprintf("ConfigValueFromHCL2Block used with non-object value %#v", v))
	}

	atys := v.Type().AttributeTypes()
	ret := make(map[string]interface{})

	for name := range schema.Attributes {
		if _, exists := atys[name]; !exists {
			continue
		}

		av := v.GetAttr(name)
		if av.IsNull() {
			// Skip nulls altogether, to better mimic how HCL1 would behave
			continue
		}
		ret[name] = ConfigValueFromHCL2(av)
	}

	for name, blockS := range schema.BlockTypes {
		if _, exists := atys[name]; !exists {
			continue
		}
		bv := v.GetAttr(name)
		if !bv.IsKnown() {
			ret[name] = UnknownVariableValue
			continue
		}
		if bv.IsNull() {
			continue
		}

		switch blockS.Nesting {

		case configschema.NestingSingle, configschema.NestingGroup:
			ret[name] = ConfigValueFromHCL2Block(bv, &blockS.Block)

		case configschema.NestingList, configschema.NestingSet:
			l := bv.LengthInt()
			if l == 0 {
				// skip empty collections to better mimic how HCL1 would behave
				continue
			}

			elems := make([]interface{}, 0, l)
			for it := bv.ElementIterator(); it.Next(); {
				_, ev := it.Element()
				if !ev.IsKnown() {
					elems = append(elems, UnknownVariableValue)
					continue
				}
				elems = append(elems, ConfigValueFromHCL2Block(ev, &blockS.Block))
			}
			ret[name] = elems

		case configschema.NestingMap:
			if bv.LengthInt() == 0 {
				// skip empty collections to better mimic how HCL1 would behave
				continue
			}

			elems := make(map[string]interface{})
			for it := bv.ElementIterator(); it.Next(); {
				ek, ev := it.Element()
				if !ev.IsKnown() {
					elems[ek.AsString()] = UnknownVariableValue
					continue
				}
				elems[ek.AsString()] = ConfigValueFromHCL2Block(ev, &blockS.Block)
			}
			ret[name] = elems
		}
	}

	return ret
}

// ConfigValueFromHCL2 converts a value from HCL2 (really, from the cty dynamic
// types library that HCL2 uses) to a value type that matches what would've
// been produced from the HCL-based interpolator for an equivalent structure.
//
// This function will transform a cty null value into a Go nil value, which
// isn't a possible outcome of the HCL/HIL-based decoder and so callers may
// need to detect and reject any null values.
func ConfigValueFromHCL2(v cty.Value) interface{} {
	if !v.IsKnown() {
		return UnknownVariableValue
	}
	if v.IsNull() {
		return nil
	}

	switch v.Type() {
	case cty.Bool:
		return v.True() // like HCL.BOOL
	case cty.String:
		return v.AsString() // like HCL token.STRING or token.HEREDOC
	case cty.Number:
		// We can't match HCL _exactly_ here because it distinguishes between
		// int and float values, but we'll get as close as we can by using
		// an int if the number is exactly representable, and a float if not.
		// The conversion to float will force precision to that of a float64,
		// which is potentially losing information from the specific number
		// given, but no worse than what HCL would've done in its own conversion
		// to float.

		f := v.AsBigFloat()
		if i, acc := f.Int64(); acc == big.Exact {
			// if we're on a 32-bit system and the number is too big for 32-bit
			// int then we'll fall through here and use a float64.
			const MaxInt = int(^uint(0) >> 1)
			const MinInt = -MaxInt - 1
			if i <= int64(MaxInt) && i >= int64(MinInt) {
				return int(i) // Like HCL token.NUMBER
			}
		}

		f64, _ := f.Float64()
		return f64 // like HCL token.FLOAT
	}

	if v.Type().IsListType() || v.Type().IsSetType() || v.Type().IsTupleType() {
		l := make([]interface{}, 0, v.LengthInt())
		it := v.ElementIterator()
		for it.Next() {
			_, ev := it.Element()
			l = append(l, ConfigValueFromHCL2(ev))
		}
		return l
	}

	if v.Type().IsMapType() || v.Type().IsObjectType() {
		l := make(map[string]interface{})
		it := v.ElementIterator()
		for it.Next() {
			ek, ev := it.Element()
			cv := ConfigValueFromHCL2(ev)
			if cv != nil {
				l[ek.AsString()] = cv
			}
		}
		return l
	}

	// If we fall out here then we have some weird type that we haven't
	// accounted for. This should never happen unless the caller is using
	// capsule types, and we don't currently have any such types defined.
	panic(fmt.Errorf("can't convert %#v to config value", v))
}

// HCL2ValueFromConfigValue is the opposite of configValueFromHCL2: it takes
// a value as would be returned from the old interpolator and turns it into
// a cty.Value so it can be used within, for example, an HCL2 EvalContext.
func HCL2ValueFromConfigValue(v interface{}) cty.Value {
	if v == nil {
		return cty.NullVal(cty.DynamicPseudoType)
	}
	if v == UnknownVariableValue {
		return cty.DynamicVal
	}

	switch tv := v.(type) {
	case bool:
		return cty.BoolVal(tv)
	case string:
		return cty.StringVal(tv)
	case int:
		return cty.NumberIntVal(int64(tv))
	case float64:
		return cty.NumberFloatVal(tv)
	case []interface{}:
		vals := make([]cty.Value, len(tv))
		for i, ev := range tv {
			vals[i] = HCL2ValueFromConfigValue(ev)
		}
		return cty.TupleVal(vals)
	case map[string]interface{}:
		vals := map[string]cty.Value{}
		for k, ev := range tv {
			vals[k] = HCL2ValueFromConfigValue(ev)
		}
		return cty.ObjectVal(vals)
	default:
		// HCL/HIL should never generate anything that isn't caught by
		// the above, so if we get here something has gone very wrong.
		panic(fmt.Errorf("can't convert %#v to cty.Value", v))
	}
}
