package states

import (
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/zclconf/go-cty/cty"
)

// Taking deep copies of states is an important operation because state is
// otherwise a mutable data structure that is challenging to share across
// many separate callers. It is important that the DeepCopy implementations
// in this file comprehensively copy all parts of the state data structure
// that could be mutated via pointers.

// DeepCopy returns a new state that contains equivalent data to the reciever
// but shares no backing memory in common.
//
// As with all methods on State, this method is not safe to use concurrently
// with writing to any portion of the recieving data structure. It is the
// caller's responsibility to ensure mutual exclusion for the duration of the
// operation, but may then freely modify the receiver and the returned copy
// independently once this method returns.
func (s *State) DeepCopy() *State {
	if s == nil {
		return nil
	}

	modules := make(map[string]*Module, len(s.Modules))
	for k, m := range s.Modules {
		modules[k] = m.DeepCopy()
	}
	return &State{
		Modules:      modules,
		CheckResults: s.CheckResults.DeepCopy(),
	}
}

// DeepCopy returns a new module state that contains equivalent data to the
// receiver but shares no backing memory in common.
//
// As with all methods on Module, this method is not safe to use concurrently
// with writing to any portion of the recieving data structure. It is the
// caller's responsibility to ensure mutual exclusion for the duration of the
// operation, but may then freely modify the receiver and the returned copy
// independently once this method returns.
func (ms *Module) DeepCopy() *Module {
	if ms == nil {
		return nil
	}

	resources := make(map[string]*Resource, len(ms.Resources))
	for k, r := range ms.Resources {
		resources[k] = r.DeepCopy()
	}
	outputValues := make(map[string]*OutputValue, len(ms.OutputValues))
	for k, v := range ms.OutputValues {
		outputValues[k] = v.DeepCopy()
	}
	localValues := make(map[string]cty.Value, len(ms.LocalValues))
	for k, v := range ms.LocalValues {
		// cty.Value is immutable, so we don't need to copy these.
		localValues[k] = v
	}

	return &Module{
		Addr:         ms.Addr, // technically mutable, but immutable by convention
		Resources:    resources,
		OutputValues: outputValues,
		LocalValues:  localValues,
	}
}

// DeepCopy returns a new resource state that contains equivalent data to the
// receiver but shares no backing memory in common.
//
// As with all methods on Resource, this method is not safe to use concurrently
// with writing to any portion of the recieving data structure. It is the
// caller's responsibility to ensure mutual exclusion for the duration of the
// operation, but may then freely modify the receiver and the returned copy
// independently once this method returns.
func (rs *Resource) DeepCopy() *Resource {
	if rs == nil {
		return nil
	}

	instances := make(map[addrs.InstanceKey]*ResourceInstance, len(rs.Instances))
	for k, i := range rs.Instances {
		instances[k] = i.DeepCopy()
	}

	return &Resource{
		Addr:           rs.Addr,
		Instances:      instances,
		ProviderConfig: rs.ProviderConfig, // technically mutable, but immutable by convention
	}
}

// DeepCopy returns a new resource instance state that contains equivalent data
// to the receiver but shares no backing memory in common.
//
// As with all methods on ResourceInstance, this method is not safe to use
// concurrently with writing to any portion of the recieving data structure. It
// is the caller's responsibility to ensure mutual exclusion for the duration
// of the operation, but may then freely modify the receiver and the returned
// copy independently once this method returns.
func (i *ResourceInstance) DeepCopy() *ResourceInstance {
	if i == nil {
		return nil
	}

	deposed := make(map[DeposedKey]*ResourceInstanceObjectSrc, len(i.Deposed))
	for k, obj := range i.Deposed {
		deposed[k] = obj.DeepCopy()
	}

	return &ResourceInstance{
		Current: i.Current.DeepCopy(),
		Deposed: deposed,
	}
}

// DeepCopy returns a new resource instance object that contains equivalent data
// to the receiver but shares no backing memory in common.
//
// As with all methods on ResourceInstanceObjectSrc, this method is not safe to
// use concurrently with writing to any portion of the recieving data structure.
// It is the caller's responsibility to ensure mutual exclusion for the duration
// of the operation, but may then freely modify the receiver and the returned
// copy independently once this method returns.
func (os *ResourceInstanceObjectSrc) DeepCopy() *ResourceInstanceObjectSrc {
	if os == nil {
		return nil
	}

	var attrsFlat map[string]string
	if os.AttrsFlat != nil {
		attrsFlat = make(map[string]string, len(os.AttrsFlat))
		for k, v := range os.AttrsFlat {
			attrsFlat[k] = v
		}
	}

	var attrsJSON []byte
	if os.AttrsJSON != nil {
		attrsJSON = make([]byte, len(os.AttrsJSON))
		copy(attrsJSON, os.AttrsJSON)
	}

	var attrPaths []cty.PathValueMarks
	if os.AttrSensitivePaths != nil {
		attrPaths = make([]cty.PathValueMarks, len(os.AttrSensitivePaths))
		copy(attrPaths, os.AttrSensitivePaths)
	}

	var private []byte
	if os.Private != nil {
		private = make([]byte, len(os.Private))
		copy(private, os.Private)
	}

	// Some addrs.Referencable implementations are technically mutable, but
	// we treat them as immutable by convention and so we don't deep-copy here.
	var dependencies []addrs.ConfigResource
	if os.Dependencies != nil {
		dependencies = make([]addrs.ConfigResource, len(os.Dependencies))
		copy(dependencies, os.Dependencies)
	}

	return &ResourceInstanceObjectSrc{
		Status:              os.Status,
		SchemaVersion:       os.SchemaVersion,
		Private:             private,
		AttrsFlat:           attrsFlat,
		AttrsJSON:           attrsJSON,
		AttrSensitivePaths:  attrPaths,
		Dependencies:        dependencies,
		CreateBeforeDestroy: os.CreateBeforeDestroy,
	}
}

// DeepCopy returns a new resource instance object that contains equivalent data
// to the receiver but shares no backing memory in common.
//
// As with all methods on ResourceInstanceObject, this method is not safe to use
// concurrently with writing to any portion of the recieving data structure. It
// is the caller's responsibility to ensure mutual exclusion for the duration
// of the operation, but may then freely modify the receiver and the returned
// copy independently once this method returns.
func (o *ResourceInstanceObject) DeepCopy() *ResourceInstanceObject {
	if o == nil {
		return nil
	}

	var private []byte
	if o.Private != nil {
		private = make([]byte, len(o.Private))
		copy(private, o.Private)
	}

	// Some addrs.Referenceable implementations are technically mutable, but
	// we treat them as immutable by convention and so we don't deep-copy here.
	var dependencies []addrs.ConfigResource
	if o.Dependencies != nil {
		dependencies = make([]addrs.ConfigResource, len(o.Dependencies))
		copy(dependencies, o.Dependencies)
	}

	return &ResourceInstanceObject{
		Value:               o.Value,
		Status:              o.Status,
		Private:             private,
		Dependencies:        dependencies,
		CreateBeforeDestroy: o.CreateBeforeDestroy,
	}
}

// DeepCopy returns a new output value state that contains equivalent data
// to the receiver but shares no backing memory in common.
//
// As with all methods on OutputValue, this method is not safe to use
// concurrently with writing to any portion of the recieving data structure. It
// is the caller's responsibility to ensure mutual exclusion for the duration
// of the operation, but may then freely modify the receiver and the returned
// copy independently once this method returns.
func (os *OutputValue) DeepCopy() *OutputValue {
	if os == nil {
		return nil
	}

	return &OutputValue{
		Addr:      os.Addr,
		Value:     os.Value,
		Sensitive: os.Sensitive,
	}
}
