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

package terraform

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"reflect"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs/configschema"
	"github.com/hashicorp/terraform/internal/configs/hcl2shim"
	"github.com/zclconf/go-cty/cty"

	"github.com/mitchellh/copystructure"
)

// DiffChangeType is an enum with the kind of changes a diff has planned.
type DiffChangeType byte

const (
	DiffInvalid DiffChangeType = iota
	DiffNone
	DiffCreate
	DiffUpdate
	DiffDestroy
	DiffDestroyCreate

	// DiffRefresh is only used in the UI for displaying diffs.
	// Managed resource reads never appear in plan, and when data source
	// reads appear they are represented as DiffCreate in core before
	// transforming to DiffRefresh in the UI layer.
	DiffRefresh // TODO: Actually use DiffRefresh in core too, for less confusion
)

// multiVal matches the index key to a flatmapped set, list or map
var multiVal = regexp.MustCompile(`\.(#|%)$`)

// Diff tracks the changes that are necessary to apply a configuration
// to an existing infrastructure.
type Diff struct {
	// Modules contains all the modules that have a diff
	Modules []*ModuleDiff
}

// Prune cleans out unused structures in the diff without affecting
// the behavior of the diff at all.
//
// This is not safe to call concurrently. This is safe to call on a
// nil Diff.
func (d *Diff) Prune() {
	if d == nil {
		return
	}

	// Prune all empty modules
	newModules := make([]*ModuleDiff, 0, len(d.Modules))
	for _, m := range d.Modules {
		// If the module isn't empty, we keep it
		if !m.Empty() {
			newModules = append(newModules, m)
		}
	}
	if len(newModules) == 0 {
		newModules = nil
	}
	d.Modules = newModules
}

// AddModule adds the module with the given path to the diff.
//
// This should be the preferred method to add module diffs since it
// allows us to optimize lookups later as well as control sorting.
func (d *Diff) AddModule(path addrs.ModuleInstance) *ModuleDiff {
	// Lower the new-style address into a legacy-style address.
	// This requires that none of the steps have instance keys, which is
	// true for all addresses at the time of implementing this because
	// "count" and "for_each" are not yet implemented for modules.
	legacyPath := make([]string, len(path))
	for i, step := range path {
		if step.InstanceKey != addrs.NoKey {
			// FIXME: Once the rest of Terraform is ready to use count and
			// for_each, remove all of this and just write the addrs.ModuleInstance
			// value itself into the ModuleState.
			panic("diff cannot represent modules with count or for_each keys")
		}

		legacyPath[i] = step.Name
	}

	m := &ModuleDiff{Path: legacyPath}
	m.init()
	d.Modules = append(d.Modules, m)
	return m
}

// ModuleByPath is used to lookup the module diff for the given path.
// This should be the preferred lookup mechanism as it allows for future
// lookup optimizations.
func (d *Diff) ModuleByPath(path addrs.ModuleInstance) *ModuleDiff {
	if d == nil {
		return nil
	}
	for _, mod := range d.Modules {
		if mod.Path == nil {
			panic("missing module path")
		}
		modPath := normalizeModulePath(mod.Path)
		if modPath.String() == path.String() {
			return mod
		}
	}
	return nil
}

// RootModule returns the ModuleState for the root module
func (d *Diff) RootModule() *ModuleDiff {
	root := d.ModuleByPath(addrs.RootModuleInstance)
	if root == nil {
		panic("missing root module")
	}
	return root
}

// Empty returns true if the diff has no changes.
func (d *Diff) Empty() bool {
	if d == nil {
		return true
	}

	for _, m := range d.Modules {
		if !m.Empty() {
			return false
		}
	}

	return true
}

// Equal compares two diffs for exact equality.
//
// This is different from the Same comparison that is supported which
// checks for operation equality taking into account computed values. Equal
// instead checks for exact equality.
func (d *Diff) Equal(d2 *Diff) bool {
	// If one is nil, they must both be nil
	if d == nil || d2 == nil {
		return d == d2
	}

	// Sort the modules
	sort.Sort(moduleDiffSort(d.Modules))
	sort.Sort(moduleDiffSort(d2.Modules))

	// Copy since we have to modify the module destroy flag to false so
	// we don't compare that. TODO: delete this when we get rid of the
	// destroy flag on modules.
	dCopy := d.DeepCopy()
	d2Copy := d2.DeepCopy()
	for _, m := range dCopy.Modules {
		m.Destroy = false
	}
	for _, m := range d2Copy.Modules {
		m.Destroy = false
	}

	// Use DeepEqual
	return reflect.DeepEqual(dCopy, d2Copy)
}

// DeepCopy performs a deep copy of all parts of the Diff, making the
// resulting Diff safe to use without modifying this one.
func (d *Diff) DeepCopy() *Diff {
	copy, err := copystructure.Config{Lock: true}.Copy(d)
	if err != nil {
		panic(err)
	}

	return copy.(*Diff)
}

func (d *Diff) String() string {
	var buf bytes.Buffer

	keys := make([]string, 0, len(d.Modules))
	lookup := make(map[string]*ModuleDiff)
	for _, m := range d.Modules {
		addr := normalizeModulePath(m.Path)
		key := addr.String()
		keys = append(keys, key)
		lookup[key] = m
	}
	sort.Strings(keys)

	for _, key := range keys {
		m := lookup[key]
		mStr := m.String()

		// If we're the root module, we just write the output directly.
		if reflect.DeepEqual(m.Path, rootModulePath) {
			buf.WriteString(mStr + "\n")
			continue
		}

		buf.WriteString(fmt.Sprintf("%s:\n", key))

		s := bufio.NewScanner(strings.NewReader(mStr))
		for s.Scan() {
			buf.WriteString(fmt.Sprintf("  %s\n", s.Text()))
		}
	}

	return strings.TrimSpace(buf.String())
}

func (d *Diff) init() {
	if d.Modules == nil {
		rootDiff := &ModuleDiff{Path: rootModulePath}
		d.Modules = []*ModuleDiff{rootDiff}
	}
	for _, m := range d.Modules {
		m.init()
	}
}

// ModuleDiff tracks the differences between resources to apply within
// a single module.
type ModuleDiff struct {
	Path      []string
	Resources map[string]*InstanceDiff
	Destroy   bool // Set only by the destroy plan
}

func (d *ModuleDiff) init() {
	if d.Resources == nil {
		d.Resources = make(map[string]*InstanceDiff)
	}
	for _, r := range d.Resources {
		r.init()
	}
}

// ChangeType returns the type of changes that the diff for this
// module includes.
//
// At a module level, this will only be DiffNone, DiffUpdate, DiffDestroy, or
// DiffCreate. If an instance within the module has a DiffDestroyCreate
// then this will register as a DiffCreate for a module.
func (d *ModuleDiff) ChangeType() DiffChangeType {
	result := DiffNone
	for _, r := range d.Resources {
		change := r.ChangeType()
		switch change {
		case DiffCreate, DiffDestroy:
			if result == DiffNone {
				result = change
			}
		case DiffDestroyCreate, DiffUpdate:
			result = DiffUpdate
		}
	}

	return result
}

// Empty returns true if the diff has no changes within this module.
func (d *ModuleDiff) Empty() bool {
	if d.Destroy {
		return false
	}

	if len(d.Resources) == 0 {
		return true
	}

	for _, rd := range d.Resources {
		if !rd.Empty() {
			return false
		}
	}

	return true
}

// Instances returns the instance diffs for the id given. This can return
// multiple instance diffs if there are counts within the resource.
func (d *ModuleDiff) Instances(id string) []*InstanceDiff {
	var result []*InstanceDiff
	for k, diff := range d.Resources {
		if k == id || strings.HasPrefix(k, id+".") {
			if !diff.Empty() {
				result = append(result, diff)
			}
		}
	}

	return result
}

// IsRoot says whether or not this module diff is for the root module.
func (d *ModuleDiff) IsRoot() bool {
	return reflect.DeepEqual(d.Path, rootModulePath)
}

// String outputs the diff in a long but command-line friendly output
// format that users can read to quickly inspect a diff.
func (d *ModuleDiff) String() string {
	var buf bytes.Buffer

	names := make([]string, 0, len(d.Resources))
	for name, _ := range d.Resources {
		names = append(names, name)
	}
	sort.Strings(names)

	for _, name := range names {
		rdiff := d.Resources[name]

		crud := "UPDATE"
		switch {
		case rdiff.RequiresNew() && (rdiff.GetDestroy() || rdiff.GetDestroyTainted()):
			crud = "DESTROY/CREATE"
		case rdiff.GetDestroy() || rdiff.GetDestroyDeposed():
			crud = "DESTROY"
		case rdiff.RequiresNew():
			crud = "CREATE"
		}

		extra := ""
		if !rdiff.GetDestroy() && rdiff.GetDestroyDeposed() {
			extra = " (deposed only)"
		}

		buf.WriteString(fmt.Sprintf(
			"%s: %s%s\n",
			crud,
			name,
			extra))

		keyLen := 0
		rdiffAttrs := rdiff.CopyAttributes()
		keys := make([]string, 0, len(rdiffAttrs))
		for key, _ := range rdiffAttrs {
			if key == "id" {
				continue
			}

			keys = append(keys, key)
			if len(key) > keyLen {
				keyLen = len(key)
			}
		}
		sort.Strings(keys)

		for _, attrK := range keys {
			attrDiff, _ := rdiff.GetAttribute(attrK)

			v := attrDiff.New
			u := attrDiff.Old
			if attrDiff.NewComputed {
				v = "<computed>"
			}

			if attrDiff.Sensitive {
				u = "<sensitive>"
				v = "<sensitive>"
			}

			updateMsg := ""
			if attrDiff.RequiresNew {
				updateMsg = " (forces new resource)"
			} else if attrDiff.Sensitive {
				updateMsg = " (attribute changed)"
			}

			buf.WriteString(fmt.Sprintf(
				"  %s:%s %#v => %#v%s\n",
				attrK,
				strings.Repeat(" ", keyLen-len(attrK)),
				u,
				v,
				updateMsg))
		}
	}

	return buf.String()
}

// InstanceDiff is the diff of a resource from some state to another.
type InstanceDiff struct {
	mu             sync.Mutex
	Attributes     map[string]*ResourceAttrDiff
	Destroy        bool
	DestroyDeposed bool
	DestroyTainted bool

	// Meta is a simple K/V map that is stored in a diff and persisted to
	// plans but otherwise is completely ignored by Terraform core. It is
	// meant to be used for additional data a resource may want to pass through.
	// The value here must only contain Go primitives and collections.
	Meta map[string]interface{}
}

func (d *InstanceDiff) Lock()   { d.mu.Lock() }
func (d *InstanceDiff) Unlock() { d.mu.Unlock() }

// ApplyToValue merges the receiver into the given base value, returning a
// new value that incorporates the planned changes. The given value must
// conform to the given schema, or this method will panic.
//
// This method is intended for shimming old subsystems that still use this
// legacy diff type to work with the new-style types.
func (d *InstanceDiff) ApplyToValue(base cty.Value, schema *configschema.Block) (cty.Value, error) {
	// Create an InstanceState attributes from our existing state.
	// We can use this to more easily apply the diff changes.
	attrs := hcl2shim.FlatmapValueFromHCL2(base)
	applied, err := d.Apply(attrs, schema)
	if err != nil {
		return base, err
	}

	val, err := hcl2shim.HCL2ValueFromFlatmap(applied, schema.ImpliedType())
	if err != nil {
		return base, err
	}

	return schema.CoerceValue(val)
}

// Apply applies the diff to the provided flatmapped attributes,
// returning the new instance attributes.
//
// This method is intended for shimming old subsystems that still use this
// legacy diff type to work with the new-style types.
func (d *InstanceDiff) Apply(attrs map[string]string, schema *configschema.Block) (map[string]string, error) {
	// We always build a new value here, even if the given diff is "empty",
	// because we might be planning to create a new instance that happens
	// to have no attributes set, and so we want to produce an empty object
	// rather than just echoing back the null old value.
	if attrs == nil {
		attrs = map[string]string{}
	}

	// Rather applying the diff to mutate the attrs, we'll copy new values into
	// here to avoid the possibility of leaving stale values.
	result := map[string]string{}

	if d.Destroy || d.DestroyDeposed || d.DestroyTainted {
		return result, nil
	}

	return d.applyBlockDiff(nil, attrs, schema)
}

func (d *InstanceDiff) applyBlockDiff(path []string, attrs map[string]string, schema *configschema.Block) (map[string]string, error) {
	result := map[string]string{}
	name := ""
	if len(path) > 0 {
		name = path[len(path)-1]
	}

	// localPrefix is used to build the local result map
	localPrefix := ""
	if name != "" {
		localPrefix = name + "."
	}

	// iterate over the schema rather than the attributes, so we can handle
	// different block types separately from plain attributes
	for n, attrSchema := range schema.Attributes {
		var err error
		newAttrs, err := d.applyAttrDiff(append(path, n), attrs, attrSchema)

		if err != nil {
			return result, err
		}

		for k, v := range newAttrs {
			result[localPrefix+k] = v
		}
	}

	blockPrefix := strings.Join(path, ".")
	if blockPrefix != "" {
		blockPrefix += "."
	}
	for n, block := range schema.BlockTypes {
		// we need to find the set of all keys that traverse this block
		candidateKeys := map[string]bool{}
		blockKey := blockPrefix + n + "."
		localBlockPrefix := localPrefix + n + "."

		// we can only trust the diff for sets, since the path changes, so don't
		// count existing values as candidate keys. If it turns out we're
		// keeping the attributes, we will catch it down below with "keepBlock"
		// after we check the set count.
		if block.Nesting != configschema.NestingSet {
			for k := range attrs {
				if strings.HasPrefix(k, blockKey) {
					nextDot := strings.Index(k[len(blockKey):], ".")
					if nextDot < 0 {
						continue
					}
					nextDot += len(blockKey)
					candidateKeys[k[len(blockKey):nextDot]] = true
				}
			}
		}

		for k, diff := range d.Attributes {
			// helper/schema should not insert nil diff values, but don't panic
			// if it does.
			if diff == nil {
				continue
			}

			if strings.HasPrefix(k, blockKey) {
				nextDot := strings.Index(k[len(blockKey):], ".")
				if nextDot < 0 {
					continue
				}

				if diff.NewRemoved {
					continue
				}

				nextDot += len(blockKey)
				candidateKeys[k[len(blockKey):nextDot]] = true
			}
		}

		// check each set candidate to see if it was removed.
		// we need to do this, because when entire sets are removed, they may
		// have the wrong key, and ony show diffs going to ""
		if block.Nesting == configschema.NestingSet {
			for k := range candidateKeys {
				indexPrefix := strings.Join(append(path, n, k), ".") + "."
				keep := false
				// now check each set element to see if it's a new diff, or one
				// that we're dropping. Since we're only applying the "New"
				// portion of the set, we can ignore diffs that only contain "Old"
				for attr, diff := range d.Attributes {
					// helper/schema should not insert nil diff values, but don't panic
					// if it does.
					if diff == nil {
						continue
					}

					if !strings.HasPrefix(attr, indexPrefix) {
						continue
					}

					// check for empty "count" keys
					if (strings.HasSuffix(attr, ".#") || strings.HasSuffix(attr, ".%")) && diff.New == "0" {
						continue
					}

					// removed items don't count either
					if diff.NewRemoved {
						continue
					}

					// this must be a diff to keep
					keep = true
					break
				}
				if !keep {
					delete(candidateKeys, k)
				}
			}
		}

		for k := range candidateKeys {
			newAttrs, err := d.applyBlockDiff(append(path, n, k), attrs, &block.Block)
			if err != nil {
				return result, err
			}

			for attr, v := range newAttrs {
				result[localBlockPrefix+attr] = v
			}
		}

		keepBlock := true
		// check this block's count diff directly first, since we may not
		// have candidates because it was removed and only set to "0"
		if diff, ok := d.Attributes[blockKey+"#"]; ok {
			if diff.New == "0" || diff.NewRemoved {
				keepBlock = false
			}
		}

		// if there was no diff at all, then we need to keep the block attributes
		if len(candidateKeys) == 0 && keepBlock {
			for k, v := range attrs {
				if strings.HasPrefix(k, blockKey) {
					// we need the key relative to this block, so remove the
					// entire prefix, then re-insert the block name.
					localKey := localBlockPrefix + k[len(blockKey):]
					result[localKey] = v
				}
			}
		}

		countAddr := strings.Join(append(path, n, "#"), ".")
		if countDiff, ok := d.Attributes[countAddr]; ok {
			if countDiff.NewComputed {
				result[localBlockPrefix+"#"] = hcl2shim.UnknownVariableValue
			} else {
				result[localBlockPrefix+"#"] = countDiff.New

				// While sets are complete, list are not, and we may not have all the
				// information to track removals. If the list was truncated, we need to
				// remove the extra items from the result.
				if block.Nesting == configschema.NestingList &&
					countDiff.New != "" && countDiff.New != hcl2shim.UnknownVariableValue {
					length, _ := strconv.Atoi(countDiff.New)
					for k := range result {
						if !strings.HasPrefix(k, localBlockPrefix) {
							continue
						}

						index := k[len(localBlockPrefix):]
						nextDot := strings.Index(index, ".")
						if nextDot < 1 {
							continue
						}
						index = index[:nextDot]
						i, err := strconv.Atoi(index)
						if err != nil {
							// this shouldn't happen since we added these
							// ourself, but make note of it just in case.
							log.Printf("[ERROR] bad list index in %q: %s", k, err)
							continue
						}
						if i >= length {
							delete(result, k)
						}
					}
				}
			}
		} else if origCount, ok := attrs[countAddr]; ok && keepBlock {
			result[localBlockPrefix+"#"] = origCount
		} else {
			result[localBlockPrefix+"#"] = countFlatmapContainerValues(localBlockPrefix+"#", result)
		}
	}

	return result, nil
}

func (d *InstanceDiff) applyAttrDiff(path []string, attrs map[string]string, attrSchema *configschema.Attribute) (map[string]string, error) {
	ty := attrSchema.Type
	switch {
	case ty.IsListType(), ty.IsTupleType(), ty.IsMapType():
		return d.applyCollectionDiff(path, attrs, attrSchema)
	case ty.IsSetType():
		return d.applySetDiff(path, attrs, attrSchema)
	default:
		return d.applySingleAttrDiff(path, attrs, attrSchema)
	}
}

func (d *InstanceDiff) applySingleAttrDiff(path []string, attrs map[string]string, attrSchema *configschema.Attribute) (map[string]string, error) {
	currentKey := strings.Join(path, ".")

	attr := path[len(path)-1]

	result := map[string]string{}
	diff := d.Attributes[currentKey]
	old, exists := attrs[currentKey]

	if diff != nil && diff.NewComputed {
		result[attr] = hcl2shim.UnknownVariableValue
		return result, nil
	}

	// "id" must exist and not be an empty string, or it must be unknown.
	// This only applied to top-level "id" fields.
	if attr == "id" && len(path) == 1 {
		if old == "" {
			result[attr] = hcl2shim.UnknownVariableValue
		} else {
			result[attr] = old
		}
		return result, nil
	}

	// attribute diffs are sometimes missed, so assume no diff means keep the
	// old value
	if diff == nil {
		if exists {
			result[attr] = old
		} else {
			// We need required values, so set those with an empty value. It
			// must be set in the config, since if it were missing it would have
			// failed validation.
			if attrSchema.Required {
				// we only set a missing string here, since bool or number types
				// would have distinct zero value which shouldn't have been
				// lost.
				if attrSchema.Type == cty.String {
					result[attr] = ""
				}
			}
		}
		return result, nil
	}

	// check for missmatched diff values
	if exists &&
		old != diff.Old &&
		old != hcl2shim.UnknownVariableValue &&
		diff.Old != hcl2shim.UnknownVariableValue {
		return result, fmt.Errorf("diff apply conflict for %s: diff expects %q, but prior value has %q", attr, diff.Old, old)
	}

	if diff.NewRemoved {
		// don't set anything in the new value
		return map[string]string{}, nil
	}

	if diff.Old == diff.New && diff.New == "" {
		// this can only be a valid empty string
		if attrSchema.Type == cty.String {
			result[attr] = ""
		}
		return result, nil
	}

	if attrSchema.Computed && diff.NewComputed {
		result[attr] = hcl2shim.UnknownVariableValue
		return result, nil
	}

	result[attr] = diff.New

	return result, nil
}

func (d *InstanceDiff) applyCollectionDiff(path []string, attrs map[string]string, attrSchema *configschema.Attribute) (map[string]string, error) {
	result := map[string]string{}

	prefix := ""
	if len(path) > 1 {
		prefix = strings.Join(path[:len(path)-1], ".") + "."
	}

	name := ""
	if len(path) > 0 {
		name = path[len(path)-1]
	}

	currentKey := prefix + name

	// check the index first for special handling
	for k, diff := range d.Attributes {
		// check the index value, which can be set, and 0
		if k == currentKey+".#" || k == currentKey+".%" || k == currentKey {
			if diff.NewRemoved {
				return result, nil
			}

			if diff.NewComputed {
				result[k[len(prefix):]] = hcl2shim.UnknownVariableValue
				return result, nil
			}

			// do what the diff tells us to here, so that it's consistent with applies
			if diff.New == "0" {
				result[k[len(prefix):]] = "0"
				return result, nil
			}
		}
	}

	// collect all the keys from the diff and the old state
	noDiff := true
	keys := map[string]bool{}
	for k := range d.Attributes {
		if !strings.HasPrefix(k, currentKey+".") {
			continue
		}
		noDiff = false
		keys[k] = true
	}

	noAttrs := true
	for k := range attrs {
		if !strings.HasPrefix(k, currentKey+".") {
			continue
		}
		noAttrs = false
		keys[k] = true
	}

	// If there's no diff and no attrs, then there's no value at all.
	// This prevents an unexpected zero-count attribute in the attributes.
	if noDiff && noAttrs {
		return result, nil
	}

	idx := "#"
	if attrSchema.Type.IsMapType() {
		idx = "%"
	}

	for k := range keys {
		// generate an schema placeholder for the values
		elSchema := &configschema.Attribute{
			Type: attrSchema.Type.ElementType(),
		}

		res, err := d.applySingleAttrDiff(append(path, k[len(currentKey)+1:]), attrs, elSchema)
		if err != nil {
			return result, err
		}

		for k, v := range res {
			result[name+"."+k] = v
		}
	}

	// Just like in nested list blocks, for simple lists we may need to fill in
	// missing empty strings.
	countKey := name + "." + idx
	count := result[countKey]
	length, _ := strconv.Atoi(count)

	if count != "" && count != hcl2shim.UnknownVariableValue &&
		attrSchema.Type.Equals(cty.List(cty.String)) {
		// insert empty strings into missing indexes
		for i := 0; i < length; i++ {
			key := fmt.Sprintf("%s.%d", name, i)
			if _, ok := result[key]; !ok {
				result[key] = ""
			}
		}
	}

	// now check for truncation in any type of list
	if attrSchema.Type.IsListType() {
		for key := range result {
			if key == countKey {
				continue
			}

			if len(key) <= len(name)+1 {
				// not sure what this is, but don't panic
				continue
			}

			index := key[len(name)+1:]

			// It is possible to have nested sets or maps, so look for another dot
			dot := strings.Index(index, ".")
			if dot > 0 {
				index = index[:dot]
			}

			// This shouldn't have any more dots, since the element type is only string.
			num, err := strconv.Atoi(index)
			if err != nil {
				log.Printf("[ERROR] bad list index in %q: %s", currentKey, err)
				continue
			}

			if num >= length {
				delete(result, key)
			}
		}
	}

	// Fill in the count value if it wasn't present in the diff for some reason,
	// or if there is no count at all.
	_, countDiff := d.Attributes[countKey]
	if result[countKey] == "" || (!countDiff && len(keys) != len(result)) {
		result[countKey] = countFlatmapContainerValues(countKey, result)
	}

	return result, nil
}

func (d *InstanceDiff) applySetDiff(path []string, attrs map[string]string, attrSchema *configschema.Attribute) (map[string]string, error) {
	// We only need this special behavior for sets of object.
	if !attrSchema.Type.ElementType().IsObjectType() {
		// The normal collection apply behavior will work okay for this one, then.
		return d.applyCollectionDiff(path, attrs, attrSchema)
	}

	// When we're dealing with a set of an object type we actually want to
	// use our normal _block type_ apply behaviors, so we'll construct ourselves
	// a synthetic schema that treats the object type as a block type and
	// then delegate to our block apply method.
	synthSchema := &configschema.Block{
		Attributes: make(map[string]*configschema.Attribute),
	}

	for name, ty := range attrSchema.Type.ElementType().AttributeTypes() {
		// We can safely make everything into an attribute here because in the
		// event that there are nested set attributes we'll end up back in
		// here again recursively and can then deal with the next level of
		// expansion.
		synthSchema.Attributes[name] = &configschema.Attribute{
			Type:     ty,
			Optional: true,
		}
	}

	parentPath := path[:len(path)-1]
	childName := path[len(path)-1]
	containerSchema := &configschema.Block{
		BlockTypes: map[string]*configschema.NestedBlock{
			childName: {
				Nesting: configschema.NestingSet,
				Block:   *synthSchema,
			},
		},
	}

	return d.applyBlockDiff(parentPath, attrs, containerSchema)
}

// countFlatmapContainerValues returns the number of values in the flatmapped container
// (set, map, list) indexed by key. The key argument is expected to include the
// trailing ".#", or ".%".
func countFlatmapContainerValues(key string, attrs map[string]string) string {
	if len(key) < 3 || !(strings.HasSuffix(key, ".#") || strings.HasSuffix(key, ".%")) {
		panic(fmt.Sprintf("invalid index value %q", key))
	}

	prefix := key[:len(key)-1]
	items := map[string]int{}

	for k := range attrs {
		if k == key {
			continue
		}
		if !strings.HasPrefix(k, prefix) {
			continue
		}

		suffix := k[len(prefix):]
		dot := strings.Index(suffix, ".")
		if dot > 0 {
			suffix = suffix[:dot]
		}

		items[suffix]++
	}
	return strconv.Itoa(len(items))
}

// ResourceAttrDiff is the diff of a single attribute of a resource.
type ResourceAttrDiff struct {
	Old         string      // Old Value
	New         string      // New Value
	NewComputed bool        // True if new value is computed (unknown currently)
	NewRemoved  bool        // True if this attribute is being removed
	NewExtra    interface{} // Extra information for the provider
	RequiresNew bool        // True if change requires new resource
	Sensitive   bool        // True if the data should not be displayed in UI output
	Type        DiffAttrType
}

// Empty returns true if the diff for this attr is neutral
func (d *ResourceAttrDiff) Empty() bool {
	return d.Old == d.New && !d.NewComputed && !d.NewRemoved
}

func (d *ResourceAttrDiff) GoString() string {
	return fmt.Sprintf("*%#v", *d)
}

// DiffAttrType is an enum type that says whether a resource attribute
// diff is an input attribute (comes from the configuration) or an
// output attribute (comes as a result of applying the configuration). An
// example input would be "ami" for AWS and an example output would be
// "private_ip".
type DiffAttrType byte

const (
	DiffAttrUnknown DiffAttrType = iota
	DiffAttrInput
	DiffAttrOutput
)

func (d *InstanceDiff) init() {
	if d.Attributes == nil {
		d.Attributes = make(map[string]*ResourceAttrDiff)
	}
}

func NewInstanceDiff() *InstanceDiff {
	return &InstanceDiff{Attributes: make(map[string]*ResourceAttrDiff)}
}

func (d *InstanceDiff) Copy() (*InstanceDiff, error) {
	if d == nil {
		return nil, nil
	}

	dCopy, err := copystructure.Config{Lock: true}.Copy(d)
	if err != nil {
		return nil, err
	}

	return dCopy.(*InstanceDiff), nil
}

// ChangeType returns the DiffChangeType represented by the diff
// for this single instance.
func (d *InstanceDiff) ChangeType() DiffChangeType {
	if d.Empty() {
		return DiffNone
	}

	if d.RequiresNew() && (d.GetDestroy() || d.GetDestroyTainted()) {
		return DiffDestroyCreate
	}

	if d.GetDestroy() || d.GetDestroyDeposed() {
		return DiffDestroy
	}

	if d.RequiresNew() {
		return DiffCreate
	}

	return DiffUpdate
}

// Empty returns true if this diff encapsulates no changes.
func (d *InstanceDiff) Empty() bool {
	if d == nil {
		return true
	}

	d.mu.Lock()
	defer d.mu.Unlock()
	return !d.Destroy &&
		!d.DestroyTainted &&
		!d.DestroyDeposed &&
		len(d.Attributes) == 0
}

// Equal compares two diffs for exact equality.
//
// This is different from the Same comparison that is supported which
// checks for operation equality taking into account computed values. Equal
// instead checks for exact equality.
func (d *InstanceDiff) Equal(d2 *InstanceDiff) bool {
	// If one is nil, they must both be nil
	if d == nil || d2 == nil {
		return d == d2
	}

	// Use DeepEqual
	return reflect.DeepEqual(d, d2)
}

// DeepCopy performs a deep copy of all parts of the InstanceDiff
func (d *InstanceDiff) DeepCopy() *InstanceDiff {
	copy, err := copystructure.Config{Lock: true}.Copy(d)
	if err != nil {
		panic(err)
	}

	return copy.(*InstanceDiff)
}

func (d *InstanceDiff) GoString() string {
	return fmt.Sprintf("*%#v", InstanceDiff{
		Attributes:     d.Attributes,
		Destroy:        d.Destroy,
		DestroyTainted: d.DestroyTainted,
		DestroyDeposed: d.DestroyDeposed,
	})
}

// RequiresNew returns true if the diff requires the creation of a new
// resource (implying the destruction of the old).
func (d *InstanceDiff) RequiresNew() bool {
	if d == nil {
		return false
	}

	d.mu.Lock()
	defer d.mu.Unlock()

	return d.requiresNew()
}

func (d *InstanceDiff) requiresNew() bool {
	if d == nil {
		return false
	}

	if d.DestroyTainted {
		return true
	}

	for _, rd := range d.Attributes {
		if rd != nil && rd.RequiresNew {
			return true
		}
	}

	return false
}

func (d *InstanceDiff) GetDestroyDeposed() bool {
	d.mu.Lock()
	defer d.mu.Unlock()

	return d.DestroyDeposed
}

func (d *InstanceDiff) SetDestroyDeposed(b bool) {
	d.mu.Lock()
	defer d.mu.Unlock()

	d.DestroyDeposed = b
}

// These methods are properly locked, for use outside other InstanceDiff
// methods but everywhere else within the terraform package.
// TODO refactor the locking scheme
func (d *InstanceDiff) SetTainted(b bool) {
	d.mu.Lock()
	defer d.mu.Unlock()

	d.DestroyTainted = b
}

func (d *InstanceDiff) GetDestroyTainted() bool {
	d.mu.Lock()
	defer d.mu.Unlock()

	return d.DestroyTainted
}

func (d *InstanceDiff) SetDestroy(b bool) {
	d.mu.Lock()
	defer d.mu.Unlock()

	d.Destroy = b
}

func (d *InstanceDiff) GetDestroy() bool {
	d.mu.Lock()
	defer d.mu.Unlock()

	return d.Destroy
}

func (d *InstanceDiff) SetAttribute(key string, attr *ResourceAttrDiff) {
	d.mu.Lock()
	defer d.mu.Unlock()

	d.Attributes[key] = attr
}

func (d *InstanceDiff) DelAttribute(key string) {
	d.mu.Lock()
	defer d.mu.Unlock()

	delete(d.Attributes, key)
}

func (d *InstanceDiff) GetAttribute(key string) (*ResourceAttrDiff, bool) {
	d.mu.Lock()
	defer d.mu.Unlock()

	attr, ok := d.Attributes[key]
	return attr, ok
}
func (d *InstanceDiff) GetAttributesLen() int {
	d.mu.Lock()
	defer d.mu.Unlock()

	return len(d.Attributes)
}

// Safely copies the Attributes map
func (d *InstanceDiff) CopyAttributes() map[string]*ResourceAttrDiff {
	d.mu.Lock()
	defer d.mu.Unlock()

	attrs := make(map[string]*ResourceAttrDiff)
	for k, v := range d.Attributes {
		attrs[k] = v
	}

	return attrs
}

// Same checks whether or not two InstanceDiff's are the "same". When
// we say "same", it is not necessarily exactly equal. Instead, it is
// just checking that the same attributes are changing, a destroy
// isn't suddenly happening, etc.
func (d *InstanceDiff) Same(d2 *InstanceDiff) (bool, string) {
	// we can safely compare the pointers without a lock
	switch {
	case d == nil && d2 == nil:
		return true, ""
	case d == nil || d2 == nil:
		return false, "one nil"
	case d == d2:
		return true, ""
	}

	d.mu.Lock()
	defer d.mu.Unlock()

	// If we're going from requiring new to NOT requiring new, then we have
	// to see if all required news were computed. If so, it is allowed since
	// computed may also mean "same value and therefore not new".
	oldNew := d.requiresNew()
	newNew := d2.RequiresNew()
	if oldNew && !newNew {
		oldNew = false

		// This section builds a list of ignorable attributes for requiresNew
		// by removing off any elements of collections going to zero elements.
		// For collections going to zero, they may not exist at all in the
		// new diff (and hence RequiresNew == false).
		ignoreAttrs := make(map[string]struct{})
		for k, diffOld := range d.Attributes {
			if !strings.HasSuffix(k, ".%") && !strings.HasSuffix(k, ".#") {
				continue
			}

			// This case is in here as a protection measure. The bug that this
			// code originally fixed (GH-11349) didn't have to deal with computed
			// so I'm not 100% sure what the correct behavior is. Best to leave
			// the old behavior.
			if diffOld.NewComputed {
				continue
			}

			// We're looking for the case a map goes to exactly 0.
			if diffOld.New != "0" {
				continue
			}

			// Found it! Ignore all of these. The prefix here is stripping
			// off the "%" so it is just "k."
			prefix := k[:len(k)-1]
			for k2, _ := range d.Attributes {
				if strings.HasPrefix(k2, prefix) {
					ignoreAttrs[k2] = struct{}{}
				}
			}
		}

		for k, rd := range d.Attributes {
			if _, ok := ignoreAttrs[k]; ok {
				continue
			}

			// If the field is requires new and NOT computed, then what
			// we have is a diff mismatch for sure. We set that the old
			// diff does REQUIRE a ForceNew.
			if rd != nil && rd.RequiresNew && !rd.NewComputed {
				oldNew = true
				break
			}
		}
	}

	if oldNew != newNew {
		return false, fmt.Sprintf(
			"diff RequiresNew; old: %t, new: %t", oldNew, newNew)
	}

	// Verify that destroy matches. The second boolean here allows us to
	// have mismatching Destroy if we're moving from RequiresNew true
	// to false above. Therefore, the second boolean will only pass if
	// we're moving from Destroy: true to false as well.
	if d.Destroy != d2.GetDestroy() && d.requiresNew() == oldNew {
		return false, fmt.Sprintf(
			"diff: Destroy; old: %t, new: %t", d.Destroy, d2.GetDestroy())
	}

	// Go through the old diff and make sure the new diff has all the
	// same attributes. To start, build up the check map to be all the keys.
	checkOld := make(map[string]struct{})
	checkNew := make(map[string]struct{})
	for k, _ := range d.Attributes {
		checkOld[k] = struct{}{}
	}
	for k, _ := range d2.CopyAttributes() {
		checkNew[k] = struct{}{}
	}

	// Make an ordered list so we are sure the approximated hashes are left
	// to process at the end of the loop
	keys := make([]string, 0, len(d.Attributes))
	for k, _ := range d.Attributes {
		keys = append(keys, k)
	}
	sort.StringSlice(keys).Sort()

	for _, k := range keys {
		diffOld := d.Attributes[k]

		if _, ok := checkOld[k]; !ok {
			// We're not checking this key for whatever reason (see where
			// check is modified).
			continue
		}

		// Remove this key since we'll never hit it again
		delete(checkOld, k)
		delete(checkNew, k)

		_, ok := d2.GetAttribute(k)
		if !ok {
			// If there's no new attribute, and the old diff expected the attribute
			// to be removed, that's just fine.
			if diffOld.NewRemoved {
				continue
			}

			// If the last diff was a computed value then the absense of
			// that value is allowed since it may mean the value ended up
			// being the same.
			if diffOld.NewComputed {
				ok = true
			}

			// No exact match, but maybe this is a set containing computed
			// values. So check if there is an approximate hash in the key
			// and if so, try to match the key.
			if strings.Contains(k, "~") {
				parts := strings.Split(k, ".")
				parts2 := append([]string(nil), parts...)

				re := regexp.MustCompile(`^~\d+$`)
				for i, part := range parts {
					if re.MatchString(part) {
						// we're going to consider this the base of a
						// computed hash, and remove all longer matching fields
						ok = true

						parts2[i] = `\d+`
						parts2 = parts2[:i+1]
						break
					}
				}

				re, err := regexp.Compile("^" + strings.Join(parts2, `\.`))
				if err != nil {
					return false, fmt.Sprintf("regexp failed to compile; err: %#v", err)
				}

				for k2, _ := range checkNew {
					if re.MatchString(k2) {
						delete(checkNew, k2)
					}
				}
			}

			// This is a little tricky, but when a diff contains a computed
			// list, set, or map that can only be interpolated after the apply
			// command has created the dependent resources, it could turn out
			// that the result is actually the same as the existing state which
			// would remove the key from the diff.
			if diffOld.NewComputed && (strings.HasSuffix(k, ".#") || strings.HasSuffix(k, ".%")) {
				ok = true
			}

			// Similarly, in a RequiresNew scenario, a list that shows up in the plan
			// diff can disappear from the apply diff, which is calculated from an
			// empty state.
			if d.requiresNew() && (strings.HasSuffix(k, ".#") || strings.HasSuffix(k, ".%")) {
				ok = true
			}

			if !ok {
				return false, fmt.Sprintf("attribute mismatch: %s", k)
			}
		}

		// search for the suffix of the base of a [computed] map, list or set.
		match := multiVal.FindStringSubmatch(k)

		if diffOld.NewComputed && len(match) == 2 {
			matchLen := len(match[1])

			// This is a computed list, set, or map, so remove any keys with
			// this prefix from the check list.
			kprefix := k[:len(k)-matchLen]
			for k2, _ := range checkOld {
				if strings.HasPrefix(k2, kprefix) {
					delete(checkOld, k2)
				}
			}
			for k2, _ := range checkNew {
				if strings.HasPrefix(k2, kprefix) {
					delete(checkNew, k2)
				}
			}
		}

		// We don't compare the values because we can't currently actually
		// guarantee to generate the same value two two diffs created from
		// the same state+config: we have some pesky interpolation functions
		// that do not behave as pure functions (uuid, timestamp) and so they
		// can be different each time a diff is produced.
		// FIXME: Re-organize our config handling so that we don't re-evaluate
		// expressions when we produce a second comparison diff during
		// apply (for EvalCompareDiff).
	}

	// Check for leftover attributes
	if len(checkNew) > 0 {
		extras := make([]string, 0, len(checkNew))
		for attr, _ := range checkNew {
			extras = append(extras, attr)
		}
		return false,
			fmt.Sprintf("extra attributes: %s", strings.Join(extras, ", "))
	}

	return true, ""
}

// moduleDiffSort implements sort.Interface to sort module diffs by path.
type moduleDiffSort []*ModuleDiff

func (s moduleDiffSort) Len() int      { return len(s) }
func (s moduleDiffSort) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s moduleDiffSort) Less(i, j int) bool {
	a := s[i]
	b := s[j]

	// If the lengths are different, then the shorter one always wins
	if len(a.Path) != len(b.Path) {
		return len(a.Path) < len(b.Path)
	}

	// Otherwise, compare lexically
	return strings.Join(a.Path, ".") < strings.Join(b.Path, ".")
}
