package configschema

import (
	"runtime"
	"sync"
	"unsafe"

	"github.com/hashicorp/hcl/v2/hcldec"
	"github.com/zclconf/go-cty/cty"
)

var mapLabelNames = []string{"key"}

// specCache is a global cache of all the generated hcldec.Spec values for
// Blocks. This cache is used by the Block.DecoderSpec method to memoize calls
// and prevent unnecessary regeneration of the spec, especially when they are
// large and deeply nested.
// Caching these externally rather than within the struct is required because
// Blocks are used by value and copied when working with NestedBlocks, and the
// copying of the value prevents any safe synchronisation of the struct itself.
//
// While we are using the *Block pointer as the cache key, and the Block
// contents are mutable, once a Block is created it is treated as immutable for
// the duration of its life. Because a Block is a representation of a logical
// schema, which cannot change while it's being used, any modifications to the
// schema during execution would be an error.
type specCache struct {
	sync.Mutex
	specs map[uintptr]hcldec.Spec
}

var decoderSpecCache = specCache{
	specs: map[uintptr]hcldec.Spec{},
}

// get returns the Spec associated with eth given Block, or nil if non is
// found.
func (s *specCache) get(b *Block) hcldec.Spec {
	s.Lock()
	defer s.Unlock()
	k := uintptr(unsafe.Pointer(b))
	return s.specs[k]
}

// set stores the given Spec as being the result of b.DecoderSpec().
func (s *specCache) set(b *Block, spec hcldec.Spec) {
	s.Lock()
	defer s.Unlock()

	// the uintptr value gets us a unique identifier for each block, without
	// tying this to the block value itself.
	k := uintptr(unsafe.Pointer(b))
	if _, ok := s.specs[k]; ok {
		return
	}

	s.specs[k] = spec

	// This must use a finalizer tied to the Block, otherwise we'll continue to
	// build up Spec values as the Blocks are recycled.
	runtime.SetFinalizer(b, s.delete)
}

// delete removes the spec associated with the given Block.
func (s *specCache) delete(b *Block) {
	s.Lock()
	defer s.Unlock()

	k := uintptr(unsafe.Pointer(b))
	delete(s.specs, k)
}

// DecoderSpec returns a hcldec.Spec that can be used to decode a HCL Body
// using the facilities in the hcldec package.
//
// The returned specification is guaranteed to return a value of the same type
// returned by method ImpliedType, but it may contain null values if any of the
// block attributes are defined as optional and/or computed respectively.
func (b *Block) DecoderSpec() hcldec.Spec {
	ret := hcldec.ObjectSpec{}
	if b == nil {
		return ret
	}

	if spec := decoderSpecCache.get(b); spec != nil {
		return spec
	}

	for name, attrS := range b.Attributes {
		ret[name] = attrS.decoderSpec(name)
	}

	for name, blockS := range b.BlockTypes {
		if _, exists := ret[name]; exists {
			// This indicates an invalid schema, since it's not valid to define
			// both an attribute and a block type of the same name. We assume
			// that the provider has already used something like
			// InternalValidate to validate their schema.
			continue
		}

		childSpec := blockS.Block.DecoderSpec()

		switch blockS.Nesting {
		case NestingSingle, NestingGroup:
			ret[name] = &hcldec.BlockSpec{
				TypeName: name,
				Nested:   childSpec,
				Required: blockS.MinItems == 1,
			}
			if blockS.Nesting == NestingGroup {
				ret[name] = &hcldec.DefaultSpec{
					Primary: ret[name],
					Default: &hcldec.LiteralSpec{
						Value: blockS.EmptyValue(),
					},
				}
			}
		case NestingList:
			// We prefer to use a list where possible, since it makes our
			// implied type more complete, but if there are any
			// dynamically-typed attributes inside we must use a tuple
			// instead, at the expense of our type then not being predictable.
			if blockS.Block.specType().HasDynamicTypes() {
				ret[name] = &hcldec.BlockTupleSpec{
					TypeName: name,
					Nested:   childSpec,
					MinItems: blockS.MinItems,
					MaxItems: blockS.MaxItems,
				}
			} else {
				ret[name] = &hcldec.BlockListSpec{
					TypeName: name,
					Nested:   childSpec,
					MinItems: blockS.MinItems,
					MaxItems: blockS.MaxItems,
				}
			}
		case NestingSet:
			// We forbid dynamically-typed attributes inside NestingSet in
			// InternalValidate, so we don't do anything special to handle that
			// here. (There is no set analog to tuple and object types, because
			// cty's set implementation depends on knowing the static type in
			// order to properly compute its internal hashes.)  We assume that
			// the provider has already used something like InternalValidate to
			// validate their schema.
			ret[name] = &hcldec.BlockSetSpec{
				TypeName: name,
				Nested:   childSpec,
				MinItems: blockS.MinItems,
				MaxItems: blockS.MaxItems,
			}
		case NestingMap:
			// We prefer to use a list where possible, since it makes our
			// implied type more complete, but if there are any
			// dynamically-typed attributes inside we must use a tuple
			// instead, at the expense of our type then not being predictable.
			if blockS.Block.specType().HasDynamicTypes() {
				ret[name] = &hcldec.BlockObjectSpec{
					TypeName:   name,
					Nested:     childSpec,
					LabelNames: mapLabelNames,
				}
			} else {
				ret[name] = &hcldec.BlockMapSpec{
					TypeName:   name,
					Nested:     childSpec,
					LabelNames: mapLabelNames,
				}
			}
		default:
			// Invalid nesting type is just ignored. It's checked by
			// InternalValidate.  We assume that the provider has already used
			// something like InternalValidate to validate their schema.
			continue
		}
	}

	decoderSpecCache.set(b, ret)
	return ret
}

func (a *Attribute) decoderSpec(name string) hcldec.Spec {
	ret := &hcldec.AttrSpec{Name: name}
	if a == nil {
		return ret
	}

	if a.NestedType != nil {
		if a.Type != cty.NilType {
			panic("Invalid attribute schema: NestedType and Type cannot both be set. This is a bug in the provider.")
		}

		ty := a.NestedType.specType()
		ret.Type = ty
		ret.Required = a.Required
		return ret
	}

	ret.Type = a.Type
	ret.Required = a.Required
	return ret
}

// listOptionalAttrsFromObject is a helper function which does *not* recurse
// into NestedType Attributes, because the optional types for each of those will
// belong to their own cty.Object definitions. It is used in other functions
// which themselves handle that recursion.
func listOptionalAttrsFromObject(o *Object) []string {
	ret := make([]string, 0)

	// This is unlikely to happen outside of tests.
	if o == nil {
		return ret
	}

	for name, attr := range o.Attributes {
		if attr.Optional || attr.Computed {
			ret = append(ret, name)
		}
	}
	return ret
}
