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

package globalref

import (
	"fmt"

	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/tfdiags"
	"github.com/zclconf/go-cty/cty"
)

// Reference combines an addrs.Reference with the address of the module
// instance or resource instance where it was found.
//
// Because of the design of the Terraform language, our main model of
// references only captures the module-local part of the reference and assumes
// that it's always clear from context which module a reference belongs to.
// That's not true for globalref because our whole purpose is to work across
// module boundaries, and so this package in particular has its own
// representation of references.
type Reference struct {
	// ContainerAddr is always either addrs.ModuleInstance or
	// addrs.AbsResourceInstance. The latter is required if LocalRef's
	// subject is either an addrs.CountAddr or addrs.ForEachAddr, so
	// we can know which resource's repetition expression it's
	// referring to.
	ContainerAddr addrs.Targetable

	// LocalRef is a reference that would be resolved in the context
	// of the module instance or resource instance given in ContainerAddr.
	LocalRef *addrs.Reference
}

func absoluteRef(containerAddr addrs.Targetable, localRef *addrs.Reference) Reference {
	ret := Reference{
		ContainerAddr: containerAddr,
		LocalRef:      localRef,
	}
	// For simplicity's sake, we always reduce the ContainerAddr to be
	// just the module address unless it's a count.index, each.key, or
	// each.value reference, because for anything else it's immaterial
	// which resource it belongs to.
	switch localRef.Subject.(type) {
	case addrs.CountAttr, addrs.ForEachAttr:
		// nothing to do
	default:
		ret.ContainerAddr = ret.ModuleAddr()
	}
	return ret
}

func absoluteRefs(containerAddr addrs.Targetable, refs []*addrs.Reference) []Reference {
	if len(refs) == 0 {
		return nil
	}

	ret := make([]Reference, len(refs))
	for i, ref := range refs {
		ret[i] = absoluteRef(containerAddr, ref)
	}
	return ret
}

// ModuleAddr returns the address of the module where the reference would
// be resolved.
//
// This is either ContainerAddr directly if it's already just a module
// instance, or the module instance part of it if it's a resource instance.
func (r Reference) ModuleAddr() addrs.ModuleInstance {
	switch addr := r.ContainerAddr.(type) {
	case addrs.ModuleInstance:
		return addr
	case addrs.AbsResourceInstance:
		return addr.Module
	default:
		// NOTE: We're intentionally using only a subset of possible
		// addrs.Targetable implementations here, so anything else
		// is invalid.
		panic(fmt.Sprintf("reference has invalid container address type %T", addr))
	}
}

// ResourceInstance returns the address of the resource where the reference
// would be resolved, if there is one.
//
// Because not all references belong to resources, the extra boolean return
// value indicates whether the returned address is valid.
func (r Reference) ResourceInstance() (addrs.AbsResourceInstance, bool) {
	switch container := r.ContainerAddr.(type) {
	case addrs.ModuleInstance:
		moduleInstance := container

		switch ref := r.LocalRef.Subject.(type) {
		case addrs.Resource:
			return ref.Instance(addrs.NoKey).Absolute(moduleInstance), true
		case addrs.ResourceInstance:
			return ref.Absolute(moduleInstance), true
		}

		return addrs.AbsResourceInstance{}, false

	case addrs.AbsResourceInstance:
		return container, true
	default:
		// NOTE: We're intentionally using only a subset of possible
		// addrs.Targetable implementations here, so anything else
		// is invalid.
		panic(fmt.Sprintf("reference has invalid container address type %T", container))
	}
}

// DebugString returns an internal (but still somewhat Terraform-language-like)
// compact string representation of the reciever, which isn't an address that
// any of our usual address parsers could accept but still captures the
// essence of what the reference represents.
//
// The DebugString result is not suitable for end-user-oriented messages.
//
// DebugString is also not suitable for use as a unique key for a reference,
// because it's ambiguous (between a no-key resource instance and a resource)
// and because it discards the source location information in the LocalRef.
func (r Reference) DebugString() string {
	// As the doc comment insinuates, we don't have any real syntax for
	// "absolute references": references are always local, and targets are
	// always absolute but only include modules and resources.
	return r.ContainerAddr.String() + "::" + r.LocalRef.DisplayString()
}

// ResourceAttr converts the Reference value to a more specific ResourceAttr
// value.
//
// Because not all references belong to resources, the extra boolean return
// value indicates whether the returned address is valid.
func (r Reference) ResourceAttr() (ResourceAttr, bool) {
	res, ok := r.ResourceInstance()
	if !ok {
		return ResourceAttr{}, ok
	}

	traversal := r.LocalRef.Remaining

	path := make(cty.Path, len(traversal))
	for si, step := range traversal {
		switch ts := step.(type) {
		case hcl.TraverseRoot:
			path[si] = cty.GetAttrStep{
				Name: ts.Name,
			}
		case hcl.TraverseAttr:
			path[si] = cty.GetAttrStep{
				Name: ts.Name,
			}
		case hcl.TraverseIndex:
			path[si] = cty.IndexStep{
				Key: ts.Key,
			}
		default:
			panic(fmt.Sprintf("unsupported traversal step %#v", step))
		}
	}

	return ResourceAttr{
		Resource: res,
		Attr:     path,
	}, true
}

// addrKey returns the referenceAddrKey value for the item that
// this reference refers to, discarding any source location information.
//
// See the referenceAddrKey doc comment for more information on what this
// is suitable for.
func (r Reference) addrKey() referenceAddrKey {
	// This is a pretty arbitrary bunch of stuff. We include the type here
	// just to differentiate between no-key resource instances and resources.
	return referenceAddrKey(fmt.Sprintf("%s(%T)%s", r.ContainerAddr.String(), r.LocalRef.Subject, r.LocalRef.DisplayString()))
}

// referenceAddrKey is a special string type which conventionally contains
// a unique string representation of the object that a reference refers to,
// although not of the reference itself because it ignores the information
// that would differentiate two different references to the same object.
//
// The actual content of a referenceAddrKey is arbitrary, for internal use
// only. and subject to change in future. We use a named type here only to
// make it easier to see when we're intentionally using strings to uniquely
// identify absolute reference addresses.
type referenceAddrKey string

// ResourceAttr represents a global resource and attribute reference.
// This is a more specific form of the Reference type since it can only refer
// to a specific AbsResource and one of its attributes.
type ResourceAttr struct {
	Resource addrs.AbsResourceInstance
	Attr     cty.Path
}

func (r ResourceAttr) DebugString() string {
	return r.Resource.String() + tfdiags.FormatCtyPath(r.Attr)
}
