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

package terraform

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

	"github.com/mitchellh/copystructure"
	"github.com/mitchellh/reflectwalk"
	"github.com/zclconf/go-cty/cty"

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

// Resource is a legacy way to identify a particular resource instance.
//
// New code should use addrs.ResourceInstance instead. This is still here
// only for codepaths that haven't been updated yet.
type Resource struct {
	// These are all used by the new EvalNode stuff.
	Name       string
	Type       string
	CountIndex int

	// These aren't really used anymore anywhere, but we keep them around
	// since we haven't done a proper cleanup yet.
	Id           string
	Info         *InstanceInfo
	Config       *ResourceConfig
	Dependencies []string
	Diff         *InstanceDiff
	Provider     ResourceProvider
	State        *InstanceState
	Flags        ResourceFlag
}

// NewResource constructs a legacy Resource object from an
// addrs.ResourceInstance value.
//
// This is provided to shim to old codepaths that haven't been updated away
// from this type yet. Since this old type is not able to represent instances
// that have string keys, this function will panic if given a resource address
// that has a string key.
func NewResource(addr addrs.ResourceInstance) *Resource {
	ret := &Resource{
		Name: addr.Resource.Name,
		Type: addr.Resource.Type,
	}

	if addr.Key != addrs.NoKey {
		switch tk := addr.Key.(type) {
		case addrs.IntKey:
			ret.CountIndex = int(tk)
		default:
			panic(fmt.Errorf("resource instance with key %#v is not supported", addr.Key))
		}
	}

	return ret
}

// ResourceKind specifies what kind of instance we're working with, whether
// its a primary instance, a tainted instance, or an orphan.
type ResourceFlag byte

// InstanceInfo is used to hold information about the instance and/or
// resource being modified.
type InstanceInfo struct {
	// Id is a unique name to represent this instance. This is not related
	// to InstanceState.ID in any way.
	Id string

	// ModulePath is the complete path of the module containing this
	// instance.
	ModulePath []string

	// Type is the resource type of this instance
	Type string

	// uniqueExtra is an internal field that can be populated to supply
	// extra metadata that is used to identify a unique instance in
	// the graph walk. This will be appended to HumanID when uniqueId
	// is called.
	uniqueExtra string
}

// NewInstanceInfo constructs an InstanceInfo from an addrs.AbsResourceInstance.
//
// InstanceInfo is a legacy type, and uses of it should be gradually replaced
// by direct use of addrs.AbsResource or addrs.AbsResourceInstance as
// appropriate.
//
// The legacy InstanceInfo type cannot represent module instances with instance
// keys, so this function will panic if given such a path. Uses of this type
// should all be removed or replaced before implementing "count" and "for_each"
// arguments on modules in order to avoid such panics.
//
// This legacy type also cannot represent resource instances with string
// instance keys. It will panic if the given key is not either NoKey or an
// IntKey.
func NewInstanceInfo(addr addrs.AbsResourceInstance) *InstanceInfo {
	// We need an old-style []string module path for InstanceInfo.
	path := make([]string, len(addr.Module))
	for i, step := range addr.Module {
		if step.InstanceKey != addrs.NoKey {
			panic("NewInstanceInfo cannot convert module instance with key")
		}
		path[i] = step.Name
	}

	// This is a funny old meaning of "id" that is no longer current. It should
	// not be used for anything users might see. Note that it does not include
	// a representation of the resource mode, and so it's impossible to
	// determine from an InstanceInfo alone whether it is a managed or data
	// resource that is being referred to.
	id := fmt.Sprintf("%s.%s", addr.Resource.Resource.Type, addr.Resource.Resource.Name)
	if addr.Resource.Resource.Mode == addrs.DataResourceMode {
		id = "data." + id
	}
	if addr.Resource.Key != addrs.NoKey {
		switch k := addr.Resource.Key.(type) {
		case addrs.IntKey:
			id = id + fmt.Sprintf(".%d", int(k))
		default:
			panic(fmt.Sprintf("NewInstanceInfo cannot convert resource instance with %T instance key", addr.Resource.Key))
		}
	}

	return &InstanceInfo{
		Id:         id,
		ModulePath: path,
		Type:       addr.Resource.Resource.Type,
	}
}

// ResourceAddress returns the address of the resource that the receiver is describing.
func (i *InstanceInfo) ResourceAddress() *ResourceAddress {
	// GROSS: for tainted and deposed instances, their status gets appended
	// to i.Id to create a unique id for the graph node. Historically these
	// ids were displayed to the user, so it's designed to be human-readable:
	//   "aws_instance.bar.0 (deposed #0)"
	//
	// So here we detect such suffixes and try to interpret them back to
	// their original meaning so we can then produce a ResourceAddress
	// with a suitable InstanceType.
	id := i.Id
	instanceType := TypeInvalid
	if idx := strings.Index(id, " ("); idx != -1 {
		remain := id[idx:]
		id = id[:idx]

		switch {
		case strings.Contains(remain, "tainted"):
			instanceType = TypeTainted
		case strings.Contains(remain, "deposed"):
			instanceType = TypeDeposed
		}
	}

	addr, err := parseResourceAddressInternal(id)
	if err != nil {
		// should never happen, since that would indicate a bug in the
		// code that constructed this InstanceInfo.
		panic(fmt.Errorf("InstanceInfo has invalid Id %s", id))
	}
	if len(i.ModulePath) > 1 {
		addr.Path = i.ModulePath[1:] // trim off "root" prefix, which is implied
	}
	if instanceType != TypeInvalid {
		addr.InstanceTypeSet = true
		addr.InstanceType = instanceType
	}
	return addr
}

// ResourceConfig is a legacy type that was formerly used to represent
// interpolatable configuration blocks. It is now only used to shim to old
// APIs that still use this type, via NewResourceConfigShimmed.
type ResourceConfig struct {
	ComputedKeys []string
	Raw          map[string]interface{}
	Config       map[string]interface{}
}

// NewResourceConfigRaw constructs a ResourceConfig whose content is exactly
// the given value.
//
// The given value may contain hcl2shim.UnknownVariableValue to signal that
// something is computed, but it must not contain unprocessed interpolation
// sequences as we might've seen in Terraform v0.11 and prior.
func NewResourceConfigRaw(raw map[string]interface{}) *ResourceConfig {
	v := hcl2shim.HCL2ValueFromConfigValue(raw)

	// This is a little weird but we round-trip the value through the hcl2shim
	// package here for two reasons: firstly, because that reduces the risk
	// of it including something unlike what NewResourceConfigShimmed would
	// produce, and secondly because it creates a copy of "raw" just in case
	// something is relying on the fact that in the old world the raw and
	// config maps were always distinct, and thus you could in principle mutate
	// one without affecting the other. (I sure hope nobody was doing that, though!)
	cfg := hcl2shim.ConfigValueFromHCL2(v).(map[string]interface{})

	return &ResourceConfig{
		Raw:    raw,
		Config: cfg,

		ComputedKeys: newResourceConfigShimmedComputedKeys(v, ""),
	}
}

// NewResourceConfigShimmed wraps a cty.Value of object type in a legacy
// ResourceConfig object, so that it can be passed to older APIs that expect
// this wrapping.
//
// The returned ResourceConfig is already interpolated and cannot be
// re-interpolated. It is, therefore, useful only to functions that expect
// an already-populated ResourceConfig which they then treat as read-only.
//
// If the given value is not of an object type that conforms to the given
// schema then this function will panic.
func NewResourceConfigShimmed(val cty.Value, schema *configschema.Block) *ResourceConfig {
	if !val.Type().IsObjectType() {
		panic(fmt.Errorf("NewResourceConfigShimmed given %#v; an object type is required", val.Type()))
	}
	ret := &ResourceConfig{}

	legacyVal := hcl2shim.ConfigValueFromHCL2Block(val, schema)
	if legacyVal != nil {
		ret.Config = legacyVal

		// Now we need to walk through our structure and find any unknown values,
		// producing the separate list ComputedKeys to represent these. We use the
		// schema here so that we can preserve the expected invariant
		// that an attribute is always either wholly known or wholly unknown, while
		// a child block can be partially unknown.
		ret.ComputedKeys = newResourceConfigShimmedComputedKeys(val, "")
	} else {
		ret.Config = make(map[string]interface{})
	}
	ret.Raw = ret.Config

	return ret
}

// Record the any config values in ComputedKeys. This field had been unused in
// helper/schema, but in the new protocol we're using this so that the SDK can
// now handle having an unknown collection. The legacy diff code doesn't
// properly handle the unknown, because it can't be expressed in the same way
// between the config and diff.
func newResourceConfigShimmedComputedKeys(val cty.Value, path string) []string {
	var ret []string
	ty := val.Type()

	if val.IsNull() {
		return ret
	}

	if !val.IsKnown() {
		// we shouldn't have an entirely unknown resource, but prevent empty
		// strings just in case
		if len(path) > 0 {
			ret = append(ret, path)
		}
		return ret
	}

	if path != "" {
		path += "."
	}
	switch {
	case ty.IsListType(), ty.IsTupleType(), ty.IsSetType():
		i := 0
		for it := val.ElementIterator(); it.Next(); i++ {
			_, subVal := it.Element()
			keys := newResourceConfigShimmedComputedKeys(subVal, fmt.Sprintf("%s%d", path, i))
			ret = append(ret, keys...)
		}

	case ty.IsMapType(), ty.IsObjectType():
		for it := val.ElementIterator(); it.Next(); {
			subK, subVal := it.Element()
			keys := newResourceConfigShimmedComputedKeys(subVal, fmt.Sprintf("%s%s", path, subK.AsString()))
			ret = append(ret, keys...)
		}
	}

	return ret
}

// DeepCopy performs a deep copy of the configuration. This makes it safe
// to modify any of the structures that are part of the resource config without
// affecting the original configuration.
func (c *ResourceConfig) DeepCopy() *ResourceConfig {
	// DeepCopying a nil should return a nil to avoid panics
	if c == nil {
		return nil
	}

	// Copy, this will copy all the exported attributes
	copy, err := copystructure.Config{Lock: true}.Copy(c)
	if err != nil {
		panic(err)
	}

	// Force the type
	result := copy.(*ResourceConfig)

	return result
}

// Equal checks the equality of two resource configs.
func (c *ResourceConfig) Equal(c2 *ResourceConfig) bool {
	// If either are nil, then they're only equal if they're both nil
	if c == nil || c2 == nil {
		return c == c2
	}

	// Sort the computed keys so they're deterministic
	sort.Strings(c.ComputedKeys)
	sort.Strings(c2.ComputedKeys)

	// Two resource configs if their exported properties are equal.
	// We don't compare "raw" because it is never used again after
	// initialization and for all intents and purposes they are equal
	// if the exported properties are equal.
	check := [][2]interface{}{
		{c.ComputedKeys, c2.ComputedKeys},
		{c.Raw, c2.Raw},
		{c.Config, c2.Config},
	}
	for _, pair := range check {
		if !reflect.DeepEqual(pair[0], pair[1]) {
			return false
		}
	}

	return true
}

// CheckSet checks that the given list of configuration keys is
// properly set. If not, errors are returned for each unset key.
//
// This is useful to be called in the Validate method of a ResourceProvider.
func (c *ResourceConfig) CheckSet(keys []string) []error {
	var errs []error

	for _, k := range keys {
		if !c.IsSet(k) {
			errs = append(errs, fmt.Errorf("%s must be set", k))
		}
	}

	return errs
}

// Get looks up a configuration value by key and returns the value.
//
// The second return value is true if the get was successful. Get will
// return the raw value if the key is computed, so you should pair this
// with IsComputed.
func (c *ResourceConfig) Get(k string) (interface{}, bool) {
	// We aim to get a value from the configuration. If it is computed,
	// then we return the pure raw value.
	source := c.Config
	if c.IsComputed(k) {
		source = c.Raw
	}

	return c.get(k, source)
}

// GetRaw looks up a configuration value by key and returns the value,
// from the raw, uninterpolated config.
//
// The second return value is true if the get was successful. Get will
// not succeed if the value is being computed.
func (c *ResourceConfig) GetRaw(k string) (interface{}, bool) {
	return c.get(k, c.Raw)
}

// IsComputed returns whether the given key is computed or not.
func (c *ResourceConfig) IsComputed(k string) bool {
	// The next thing we do is check the config if we get a computed
	// value out of it.
	v, ok := c.get(k, c.Config)
	if !ok {
		return false
	}

	// If value is nil, then it isn't computed
	if v == nil {
		return false
	}

	// Test if the value contains an unknown value
	var w unknownCheckWalker
	if err := reflectwalk.Walk(v, &w); err != nil {
		panic(err)
	}

	return w.Unknown
}

// IsSet checks if the key in the configuration is set. A key is set if
// it has a value or the value is being computed (is unknown currently).
//
// This function should be used rather than checking the keys of the
// raw configuration itself, since a key may be omitted from the raw
// configuration if it is being computed.
func (c *ResourceConfig) IsSet(k string) bool {
	if c == nil {
		return false
	}

	if c.IsComputed(k) {
		return true
	}

	if _, ok := c.Get(k); ok {
		return true
	}

	return false
}

func (c *ResourceConfig) get(
	k string, raw map[string]interface{}) (interface{}, bool) {
	parts := strings.Split(k, ".")
	if len(parts) == 1 && parts[0] == "" {
		parts = nil
	}

	var current interface{} = raw
	var previous interface{} = nil
	for i, part := range parts {
		if current == nil {
			return nil, false
		}

		cv := reflect.ValueOf(current)
		switch cv.Kind() {
		case reflect.Map:
			previous = current
			v := cv.MapIndex(reflect.ValueOf(part))
			if !v.IsValid() {
				if i > 0 && i != (len(parts)-1) {
					tryKey := strings.Join(parts[i:], ".")
					v := cv.MapIndex(reflect.ValueOf(tryKey))
					if !v.IsValid() {
						return nil, false
					}

					return v.Interface(), true
				}

				return nil, false
			}

			current = v.Interface()
		case reflect.Slice:
			previous = current

			if part == "#" {
				// If any value in a list is computed, this whole thing
				// is computed and we can't read any part of it.
				for i := 0; i < cv.Len(); i++ {
					if v := cv.Index(i).Interface(); v == hcl2shim.UnknownVariableValue {
						return v, true
					}
				}

				current = cv.Len()
			} else {
				i, err := strconv.ParseInt(part, 0, 0)
				if err != nil {
					return nil, false
				}
				if int(i) < 0 || int(i) >= cv.Len() {
					return nil, false
				}
				current = cv.Index(int(i)).Interface()
			}
		case reflect.String:
			// This happens when map keys contain "." and have a common
			// prefix so were split as path components above.
			actualKey := strings.Join(parts[i-1:], ".")
			if prevMap, ok := previous.(map[string]interface{}); ok {
				v, ok := prevMap[actualKey]
				return v, ok
			}

			return nil, false
		default:
			panic(fmt.Sprintf("Unknown kind: %s", cv.Kind()))
		}
	}

	return current, true
}

// unknownCheckWalker
type unknownCheckWalker struct {
	Unknown bool
}

func (w *unknownCheckWalker) Primitive(v reflect.Value) error {
	if v.Interface() == hcl2shim.UnknownVariableValue {
		w.Unknown = true
	}

	return nil
}
