package configschema

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

// ImpliedType returns the cty.Type that would result from decoding a
// configuration block using the receiving block schema.
//
// The type returned from Block.ImpliedType differs from the type returned by
// hcldec.ImpliedType in that there will be no objects with optional
// attributes, since this value is not to be used for the decoding of
// configuration.
//
// ImpliedType always returns a result, even if the given schema is
// inconsistent. Code that creates configschema.Block objects should be
// tested using the InternalValidate method to detect any inconsistencies
// that would cause this method to fall back on defaults and assumptions.
func (b *Block) ImpliedType() cty.Type {
	return b.specType().WithoutOptionalAttributesDeep()
}

// specType returns the cty.Type used for decoding a configuration
// block using the receiving block schema. This is the type used internally by
// hcldec to decode configuration.
func (b *Block) specType() cty.Type {
	if b == nil {
		return cty.EmptyObject
	}

	return hcldec.ImpliedType(b.DecoderSpec())
}

// ContainsSensitive returns true if any of the attributes of the receiving
// block or any of its descendent blocks are marked as sensitive.
//
// Blocks themselves cannot be sensitive as a whole -- sensitivity is a
// per-attribute idea -- but sometimes we want to include a whole object
// decoded from a block in some UI output, and that is safe to do only if
// none of the contained attributes are sensitive.
func (b *Block) ContainsSensitive() bool {
	for _, attrS := range b.Attributes {
		if attrS.Sensitive {
			return true
		}
		if attrS.NestedType != nil && attrS.NestedType.ContainsSensitive() {
			return true
		}
	}
	for _, blockS := range b.BlockTypes {
		if blockS.ContainsSensitive() {
			return true
		}
	}
	return false
}

// ImpliedType returns the cty.Type that would result from decoding a Block's
// ImpliedType and getting the resulting AttributeType.
//
// ImpliedType always returns a result, even if the given schema is
// inconsistent. Code that creates configschema.Object objects should be tested
// using the InternalValidate method to detect any inconsistencies that would
// cause this method to fall back on defaults and assumptions.
func (a *Attribute) ImpliedType() cty.Type {
	if a.NestedType != nil {
		return a.NestedType.specType().WithoutOptionalAttributesDeep()
	}
	return a.Type
}

// ImpliedType returns the cty.Type that would result from decoding a
// NestedType Attribute using the receiving block schema.
//
// ImpliedType always returns a result, even if the given schema is
// inconsistent. Code that creates configschema.Object objects should be tested
// using the InternalValidate method to detect any inconsistencies that would
// cause this method to fall back on defaults and assumptions.
func (o *Object) ImpliedType() cty.Type {
	return o.specType().WithoutOptionalAttributesDeep()
}

// specType returns the cty.Type used for decoding a NestedType Attribute using
// the receiving block schema.
func (o *Object) specType() cty.Type {
	if o == nil {
		return cty.EmptyObject
	}

	attrTys := make(map[string]cty.Type, len(o.Attributes))
	for name, attrS := range o.Attributes {
		if attrS.NestedType != nil {
			attrTys[name] = attrS.NestedType.specType()
		} else {
			attrTys[name] = attrS.Type
		}
	}
	optAttrs := listOptionalAttrsFromObject(o)

	var ret cty.Type
	if len(optAttrs) > 0 {
		ret = cty.ObjectWithOptionalAttrs(attrTys, optAttrs)
	} else {
		ret = cty.Object(attrTys)
	}
	switch o.Nesting {
	case NestingSingle:
		return ret
	case NestingList:
		return cty.List(ret)
	case NestingMap:
		return cty.Map(ret)
	case NestingSet:
		return cty.Set(ret)
	default: // Should never happen
		return cty.EmptyObject
	}
}

// ContainsSensitive returns true if any of the attributes of the receiving
// Object are marked as sensitive.
func (o *Object) ContainsSensitive() bool {
	for _, attrS := range o.Attributes {
		if attrS.Sensitive {
			return true
		}
		if attrS.NestedType != nil && attrS.NestedType.ContainsSensitive() {
			return true
		}
	}
	return false
}
