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

package schema

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"sync"

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

// newValueWriter is a minor re-implementation of MapFieldWriter to include
// keys that should be marked as computed, to represent the new part of a
// pseudo-diff.
type newValueWriter struct {
	*MapFieldWriter

	// A list of keys that should be marked as computed.
	computedKeys map[string]bool

	// A lock to prevent races on writes. The underlying writer will have one as
	// well - this is for computed keys.
	lock sync.Mutex

	// To be used with init.
	once sync.Once
}

// init performs any initialization tasks for the newValueWriter.
func (w *newValueWriter) init() {
	if w.computedKeys == nil {
		w.computedKeys = make(map[string]bool)
	}
}

// WriteField overrides MapValueWriter's WriteField, adding the ability to flag
// the address as computed.
func (w *newValueWriter) WriteField(address []string, value interface{}, computed bool) error {
	// Fail the write if we have a non-nil value and computed is true.
	// NewComputed values should not have a value when written.
	if value != nil && computed {
		return errors.New("Non-nil value with computed set")
	}

	if err := w.MapFieldWriter.WriteField(address, value); err != nil {
		return err
	}

	w.once.Do(w.init)

	w.lock.Lock()
	defer w.lock.Unlock()
	if computed {
		w.computedKeys[strings.Join(address, ".")] = true
	}
	return nil
}

// ComputedKeysMap returns the underlying computed keys map.
func (w *newValueWriter) ComputedKeysMap() map[string]bool {
	w.once.Do(w.init)
	return w.computedKeys
}

// newValueReader is a minor re-implementation of MapFieldReader and is the
// read counterpart to MapValueWriter, allowing the read of keys flagged as
// computed to accommodate the diff override logic in ResourceDiff.
type newValueReader struct {
	*MapFieldReader

	// The list of computed keys from a newValueWriter.
	computedKeys map[string]bool
}

// ReadField reads the values from the underlying writer, returning the
// computed value if it is found as well.
func (r *newValueReader) ReadField(address []string) (FieldReadResult, error) {
	addrKey := strings.Join(address, ".")
	v, err := r.MapFieldReader.ReadField(address)
	if err != nil {
		return FieldReadResult{}, err
	}
	for computedKey := range r.computedKeys {
		if childAddrOf(addrKey, computedKey) {
			if strings.HasSuffix(addrKey, ".#") {
				// This is a count value for a list or set that has been marked as
				// computed, or a sub-list/sub-set of a complex resource that has
				// been marked as computed.  We need to pass through to other readers
				// so that an accurate previous count can be fetched for the diff.
				v.Exists = false
			}
			v.Computed = true
		}
	}

	return v, nil
}

// ResourceDiff is used to query and make custom changes to an in-flight diff.
// It can be used to veto particular changes in the diff, customize the diff
// that has been created, or diff values not controlled by config.
//
// The object functions similar to ResourceData, however most notably lacks
// Set, SetPartial, and Partial, as it should be used to change diff values
// only.  Most other first-class ResourceData functions exist, namely Get,
// GetOk, HasChange, and GetChange exist.
//
// All functions in ResourceDiff, save for ForceNew, can only be used on
// computed fields.
type ResourceDiff struct {
	// The schema for the resource being worked on.
	schema map[string]*Schema

	// The current config for this resource.
	config *terraform.ResourceConfig

	// The state for this resource as it exists post-refresh, after the initial
	// diff.
	state *terraform.InstanceState

	// The diff created by Terraform. This diff is used, along with state,
	// config, and custom-set diff data, to provide a multi-level reader
	// experience similar to ResourceData.
	diff *terraform.InstanceDiff

	// The internal reader structure that contains the state, config, the default
	// diff, and the new diff.
	multiReader *MultiLevelFieldReader

	// A writer that writes overridden new fields.
	newWriter *newValueWriter

	// Tracks which keys have been updated by ResourceDiff to ensure that the
	// diff does not get re-run on keys that were not touched, or diffs that were
	// just removed (re-running on the latter would just roll back the removal).
	updatedKeys map[string]bool

	// Tracks which keys were flagged as forceNew. These keys are not saved in
	// newWriter, but we need to track them so that they can be re-diffed later.
	forcedNewKeys map[string]bool
}

// newResourceDiff creates a new ResourceDiff instance.
func newResourceDiff(schema map[string]*Schema, config *terraform.ResourceConfig, state *terraform.InstanceState, diff *terraform.InstanceDiff) *ResourceDiff {
	d := &ResourceDiff{
		config: config,
		state:  state,
		diff:   diff,
		schema: schema,
	}

	d.newWriter = &newValueWriter{
		MapFieldWriter: &MapFieldWriter{Schema: d.schema},
	}
	readers := make(map[string]FieldReader)
	var stateAttributes map[string]string
	if d.state != nil {
		stateAttributes = d.state.Attributes
		readers["state"] = &MapFieldReader{
			Schema: d.schema,
			Map:    BasicMapReader(stateAttributes),
		}
	}
	if d.config != nil {
		readers["config"] = &ConfigFieldReader{
			Schema: d.schema,
			Config: d.config,
		}
	}
	if d.diff != nil {
		readers["diff"] = &DiffFieldReader{
			Schema: d.schema,
			Diff:   d.diff,
			Source: &MultiLevelFieldReader{
				Levels:  []string{"state", "config"},
				Readers: readers,
			},
		}
	}
	readers["newDiff"] = &newValueReader{
		MapFieldReader: &MapFieldReader{
			Schema: d.schema,
			Map:    BasicMapReader(d.newWriter.Map()),
		},
		computedKeys: d.newWriter.ComputedKeysMap(),
	}
	d.multiReader = &MultiLevelFieldReader{
		Levels: []string{
			"state",
			"config",
			"diff",
			"newDiff",
		},

		Readers: readers,
	}

	d.updatedKeys = make(map[string]bool)
	d.forcedNewKeys = make(map[string]bool)

	return d
}

// UpdatedKeys returns the keys that were updated by this ResourceDiff run.
// These are the only keys that a diff should be re-calculated for.
//
// This is the combined result of both keys for which diff values were updated
// for or cleared, and also keys that were flagged to be re-diffed as a result
// of ForceNew.
func (d *ResourceDiff) UpdatedKeys() []string {
	var s []string
	for k := range d.updatedKeys {
		s = append(s, k)
	}
	for k := range d.forcedNewKeys {
		for _, l := range s {
			if k == l {
				break
			}
		}
		s = append(s, k)
	}
	return s
}

// Clear wipes the diff for a particular key. It is called by ResourceDiff's
// functionality to remove any possibility of conflicts, but can be called on
// its own to just remove a specific key from the diff completely.
//
// Note that this does not wipe an override. This function is only allowed on
// computed keys.
func (d *ResourceDiff) Clear(key string) error {
	if err := d.checkKey(key, "Clear", true); err != nil {
		return err
	}

	return d.clear(key)
}

func (d *ResourceDiff) clear(key string) error {
	// Check the schema to make sure that this key exists first.
	schemaL := addrToSchema(strings.Split(key, "."), d.schema)
	if len(schemaL) == 0 {
		return fmt.Errorf("%s is not a valid key", key)
	}

	for k := range d.diff.Attributes {
		if strings.HasPrefix(k, key) {
			delete(d.diff.Attributes, k)
		}
	}
	return nil
}

// GetChangedKeysPrefix helps to implement Resource.CustomizeDiff
// where we need to act on all nested fields
// without calling out each one separately
func (d *ResourceDiff) GetChangedKeysPrefix(prefix string) []string {
	keys := make([]string, 0)
	for k := range d.diff.Attributes {
		if strings.HasPrefix(k, prefix) {
			keys = append(keys, k)
		}
	}
	return keys
}

// diffChange helps to implement resourceDiffer and derives its change values
// from ResourceDiff's own change data, in addition to existing diff, config, and state.
func (d *ResourceDiff) diffChange(key string) (interface{}, interface{}, bool, bool, bool) {
	old, new, customized := d.getChange(key)

	if !old.Exists {
		old.Value = nil
	}
	if !new.Exists || d.removed(key) {
		new.Value = nil
	}

	return old.Value, new.Value, !reflect.DeepEqual(old.Value, new.Value), new.Computed, customized
}

// SetNew is used to set a new diff value for the mentioned key. The value must
// be correct for the attribute's schema (mostly relevant for maps, lists, and
// sets). The original value from the state is used as the old value.
//
// This function is only allowed on computed attributes.
func (d *ResourceDiff) SetNew(key string, value interface{}) error {
	if err := d.checkKey(key, "SetNew", false); err != nil {
		return err
	}

	return d.setDiff(key, value, false)
}

// SetNewComputed functions like SetNew, except that it blanks out a new value
// and marks it as computed.
//
// This function is only allowed on computed attributes.
func (d *ResourceDiff) SetNewComputed(key string) error {
	if err := d.checkKey(key, "SetNewComputed", false); err != nil {
		return err
	}

	return d.setDiff(key, nil, true)
}

// setDiff performs common diff setting behaviour.
func (d *ResourceDiff) setDiff(key string, new interface{}, computed bool) error {
	if err := d.clear(key); err != nil {
		return err
	}

	if err := d.newWriter.WriteField(strings.Split(key, "."), new, computed); err != nil {
		return fmt.Errorf("Cannot set new diff value for key %s: %s", key, err)
	}

	d.updatedKeys[key] = true

	return nil
}

// ForceNew force-flags ForceNew in the schema for a specific key, and
// re-calculates its diff, effectively causing this attribute to force a new
// resource.
//
// Keep in mind that forcing a new resource will force a second run of the
// resource's CustomizeDiff function (with a new ResourceDiff) once the current
// one has completed. This second run is performed without state. This behavior
// will be the same as if a new resource is being created and is performed to
// ensure that the diff looks like the diff for a new resource as much as
// possible. CustomizeDiff should expect such a scenario and act correctly.
//
// This function is a no-op/error if there is no diff.
//
// Note that the change to schema is permanent for the lifecycle of this
// specific ResourceDiff instance.
func (d *ResourceDiff) ForceNew(key string) error {
	if !d.HasChange(key) {
		return fmt.Errorf("ForceNew: No changes for %s", key)
	}

	keyParts := strings.Split(key, ".")
	var schema *Schema
	schemaL := addrToSchema(keyParts, d.schema)
	if len(schemaL) > 0 {
		schema = schemaL[len(schemaL)-1]
	} else {
		return fmt.Errorf("ForceNew: %s is not a valid key", key)
	}

	schema.ForceNew = true

	// Flag this for a re-diff. Don't save any values to guarantee that existing
	// diffs aren't messed with, as this gets messy when dealing with complex
	// structures, zero values, etc.
	d.forcedNewKeys[keyParts[0]] = true

	return nil
}

// Get hands off to ResourceData.Get.
func (d *ResourceDiff) Get(key string) interface{} {
	r, _ := d.GetOk(key)
	return r
}

// GetChange gets the change between the state and diff, checking first to see
// if an overridden diff exists.
//
// This implementation differs from ResourceData's in the way that we first get
// results from the exact levels for the new diff, then from state and diff as
// per normal.
func (d *ResourceDiff) GetChange(key string) (interface{}, interface{}) {
	old, new, _ := d.getChange(key)
	return old.Value, new.Value
}

// GetOk functions the same way as ResourceData.GetOk, but it also checks the
// new diff levels to provide data consistent with the current state of the
// customized diff.
func (d *ResourceDiff) GetOk(key string) (interface{}, bool) {
	r := d.get(strings.Split(key, "."), "newDiff")
	exists := r.Exists && !r.Computed
	if exists {
		// If it exists, we also want to verify it is not the zero-value.
		value := r.Value
		zero := r.Schema.Type.Zero()

		if eq, ok := value.(Equal); ok {
			exists = !eq.Equal(zero)
		} else {
			exists = !reflect.DeepEqual(value, zero)
		}
	}

	return r.Value, exists
}

// GetOkExists functions the same way as GetOkExists within ResourceData, but
// it also checks the new diff levels to provide data consistent with the
// current state of the customized diff.
//
// This is nearly the same function as GetOk, yet it does not check
// for the zero value of the attribute's type. This allows for attributes
// without a default, to fully check for a literal assignment, regardless
// of the zero-value for that type.
func (d *ResourceDiff) GetOkExists(key string) (interface{}, bool) {
	r := d.get(strings.Split(key, "."), "newDiff")
	exists := r.Exists && !r.Computed
	return r.Value, exists
}

// NewValueKnown returns true if the new value for the given key is available
// as its final value at diff time. If the return value is false, this means
// either the value is based of interpolation that was unavailable at diff
// time, or that the value was explicitly marked as computed by SetNewComputed.
func (d *ResourceDiff) NewValueKnown(key string) bool {
	r := d.get(strings.Split(key, "."), "newDiff")
	return !r.Computed
}

// HasChange checks to see if there is a change between state and the diff, or
// in the overridden diff.
func (d *ResourceDiff) HasChange(key string) bool {
	old, new := d.GetChange(key)

	// If the type implements the Equal interface, then call that
	// instead of just doing a reflect.DeepEqual. An example where this is
	// needed is *Set
	if eq, ok := old.(Equal); ok {
		return !eq.Equal(new)
	}

	return !reflect.DeepEqual(old, new)
}

// Id returns the ID of this resource.
//
// Note that technically, ID does not change during diffs (it either has
// already changed in the refresh, or will change on update), hence we do not
// support updating the ID or fetching it from anything else other than state.
func (d *ResourceDiff) Id() string {
	var result string

	if d.state != nil {
		result = d.state.ID
	}
	return result
}

// getChange gets values from two different levels, designed for use in
// diffChange, HasChange, and GetChange.
//
// This implementation differs from ResourceData's in the way that we first get
// results from the exact levels for the new diff, then from state and diff as
// per normal.
func (d *ResourceDiff) getChange(key string) (getResult, getResult, bool) {
	old := d.get(strings.Split(key, "."), "state")
	var new getResult
	for p := range d.updatedKeys {
		if childAddrOf(key, p) {
			new = d.getExact(strings.Split(key, "."), "newDiff")
			return old, new, true
		}
	}
	new = d.get(strings.Split(key, "."), "newDiff")
	return old, new, false
}

// removed checks to see if the key is present in the existing, pre-customized
// diff and if it was marked as NewRemoved.
func (d *ResourceDiff) removed(k string) bool {
	diff, ok := d.diff.Attributes[k]
	if !ok {
		return false
	}
	return diff.NewRemoved
}

// get performs the appropriate multi-level reader logic for ResourceDiff,
// starting at source. Refer to newResourceDiff for the level order.
func (d *ResourceDiff) get(addr []string, source string) getResult {
	result, err := d.multiReader.ReadFieldMerge(addr, source)
	if err != nil {
		panic(err)
	}

	return d.finalizeResult(addr, result)
}

// getExact gets an attribute from the exact level referenced by source.
func (d *ResourceDiff) getExact(addr []string, source string) getResult {
	result, err := d.multiReader.ReadFieldExact(addr, source)
	if err != nil {
		panic(err)
	}

	return d.finalizeResult(addr, result)
}

// finalizeResult does some post-processing of the result produced by get and getExact.
func (d *ResourceDiff) finalizeResult(addr []string, result FieldReadResult) getResult {
	// If the result doesn't exist, then we set the value to the zero value
	var schema *Schema
	if schemaL := addrToSchema(addr, d.schema); len(schemaL) > 0 {
		schema = schemaL[len(schemaL)-1]
	}

	if result.Value == nil && schema != nil {
		result.Value = result.ValueOrZero(schema)
	}

	// Transform the FieldReadResult into a getResult. It might be worth
	// merging these two structures one day.
	return getResult{
		Value:          result.Value,
		ValueProcessed: result.ValueProcessed,
		Computed:       result.Computed,
		Exists:         result.Exists,
		Schema:         schema,
	}
}

// childAddrOf does a comparison of two addresses to see if one is the child of
// the other.
func childAddrOf(child, parent string) bool {
	cs := strings.Split(child, ".")
	ps := strings.Split(parent, ".")
	if len(ps) > len(cs) {
		return false
	}
	return reflect.DeepEqual(ps, cs[:len(ps)])
}

// checkKey checks the key to make sure it exists and is computed.
func (d *ResourceDiff) checkKey(key, caller string, nested bool) error {
	var schema *Schema
	if nested {
		keyParts := strings.Split(key, ".")
		schemaL := addrToSchema(keyParts, d.schema)
		if len(schemaL) > 0 {
			schema = schemaL[len(schemaL)-1]
		}
	} else {
		s, ok := d.schema[key]
		if ok {
			schema = s
		}
	}
	if schema == nil {
		return fmt.Errorf("%s: invalid key: %s", caller, key)
	}
	if !schema.Computed {
		return fmt.Errorf("%s only operates on computed keys - %s is not one", caller, key)
	}
	return nil
}
