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

package differ

import (
	"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
	"github.com/zclconf/go-cty/cty"
	ctyjson "github.com/zclconf/go-cty/cty/json"

	"github.com/hashicorp/terraform/internal/command/jsonformat/computed"

	"github.com/hashicorp/terraform/internal/command/jsonprovider"
)

func ComputeDiffForAttribute(change structured.Change, attribute *jsonprovider.Attribute) computed.Diff {
	if attribute.AttributeNestedType != nil {
		return computeDiffForNestedAttribute(change, attribute.AttributeNestedType)
	}
	return ComputeDiffForType(change, unmarshalAttribute(attribute))
}

func computeDiffForNestedAttribute(change structured.Change, nested *jsonprovider.NestedType) computed.Diff {
	if sensitive, ok := checkForSensitiveNestedAttribute(change, nested); ok {
		return sensitive
	}

	if computed, ok := checkForUnknownNestedAttribute(change, nested); ok {
		return computed
	}

	switch NestingMode(nested.NestingMode) {
	case nestingModeSingle, nestingModeGroup:
		return computeAttributeDiffAsNestedObject(change, nested.Attributes)
	case nestingModeMap:
		return computeAttributeDiffAsNestedMap(change, nested.Attributes)
	case nestingModeList:
		return computeAttributeDiffAsNestedList(change, nested.Attributes)
	case nestingModeSet:
		return computeAttributeDiffAsNestedSet(change, nested.Attributes)
	default:
		panic("unrecognized nesting mode: " + nested.NestingMode)
	}
}

func ComputeDiffForType(change structured.Change, ctype cty.Type) computed.Diff {
	if sensitive, ok := checkForSensitiveType(change, ctype); ok {
		return sensitive
	}

	if computed, ok := checkForUnknownType(change, ctype); ok {
		return computed
	}

	switch {
	case ctype == cty.NilType, ctype == cty.DynamicPseudoType:
		// Forward nil or dynamic types over to be processed as outputs.
		// There is nothing particularly special about the way outputs are
		// processed that make this unsafe, we could just as easily call this
		// function computeChangeForDynamicValues(), but external callers will
		// only be in this situation when processing outputs so this function
		// is named for their benefit.
		return ComputeDiffForOutput(change)
	case ctype.IsPrimitiveType():
		return computeAttributeDiffAsPrimitive(change, ctype)
	case ctype.IsObjectType():
		return computeAttributeDiffAsObject(change, ctype.AttributeTypes())
	case ctype.IsMapType():
		return computeAttributeDiffAsMap(change, ctype.ElementType())
	case ctype.IsListType():
		return computeAttributeDiffAsList(change, ctype.ElementType())
	case ctype.IsTupleType():
		return computeAttributeDiffAsTuple(change, ctype.TupleElementTypes())
	case ctype.IsSetType():
		return computeAttributeDiffAsSet(change, ctype.ElementType())
	default:
		panic("unrecognized type: " + ctype.FriendlyName())
	}
}

func unmarshalAttribute(attribute *jsonprovider.Attribute) cty.Type {
	ctyType, err := ctyjson.UnmarshalType(attribute.AttributeType)
	if err != nil {
		panic("could not unmarshal attribute type: " + err.Error())
	}
	return ctyType
}
