package jsonconfig

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/hcl/v2/hcldec"
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs/configschema"
	"github.com/hashicorp/terraform/internal/lang"
	"github.com/hashicorp/terraform/internal/lang/blocktoattr"
	"github.com/zclconf/go-cty/cty"
	ctyjson "github.com/zclconf/go-cty/cty/json"
)

// expression represents any unparsed expression
type expression struct {
	// "constant_value" is set only if the expression contains no references to
	// other objects, in which case it gives the resulting constant value. This
	// is mapped as for the individual values in the common value
	// representation.
	ConstantValue json.RawMessage `json:"constant_value,omitempty"`

	// Alternatively, "references" will be set to a list of references in the
	// expression. Multi-step references will be unwrapped and duplicated for
	// each significant traversal step, allowing callers to more easily
	// recognize the objects they care about without attempting to parse the
	// expressions. Callers should only use string equality checks here, since
	// the syntax may be extended in future releases.
	References []string `json:"references,omitempty"`
}

func marshalExpression(ex hcl.Expression) expression {
	var ret expression
	if ex == nil {
		return ret
	}

	val, _ := ex.Value(nil)
	if val != cty.NilVal {
		valJSON, _ := ctyjson.Marshal(val, val.Type())
		ret.ConstantValue = valJSON
	}

	refs, _ := lang.ReferencesInExpr(ex)
	if len(refs) > 0 {
		var varString []string
		for _, ref := range refs {
			// We work backwards here, starting with the full reference +
			// reamining traversal, and then unwrapping the remaining traversals
			// into parts until we end up at the smallest referencable address.
			remains := ref.Remaining
			for len(remains) > 0 {
				varString = append(varString, fmt.Sprintf("%s%s", ref.Subject, traversalStr(remains)))
				remains = remains[:(len(remains) - 1)]
			}
			varString = append(varString, ref.Subject.String())

			switch ref.Subject.(type) {
			case addrs.ModuleCallInstance:
				if ref.Subject.(addrs.ModuleCallInstance).Key != addrs.NoKey {
					// Include the module call, without the key
					varString = append(varString, ref.Subject.(addrs.ModuleCallInstance).Call.String())
				}
			case addrs.ResourceInstance:
				if ref.Subject.(addrs.ResourceInstance).Key != addrs.NoKey {
					// Include the resource, without the key
					varString = append(varString, ref.Subject.(addrs.ResourceInstance).Resource.String())
				}
			case addrs.ModuleCallInstanceOutput:
				// Include the module name, without the output name
				varString = append(varString, ref.Subject.(addrs.ModuleCallInstanceOutput).Call.String())
			}
		}
		ret.References = varString
	}

	return ret
}

func (e *expression) Empty() bool {
	return e.ConstantValue == nil && e.References == nil
}

// expressions is used to represent the entire content of a block. Attribute
// arguments are mapped directly with the attribute name as key and an
// expression as value.
type expressions map[string]interface{}

func marshalExpressions(body hcl.Body, schema *configschema.Block) expressions {
	// Since we want the raw, un-evaluated expressions we need to use the
	// low-level HCL API here, rather than the hcldec decoder API. That means we
	// need the low-level schema.
	lowSchema := hcldec.ImpliedSchema(schema.DecoderSpec())
	// (lowSchema is an hcl.BodySchema:
	// https://godoc.org/github.com/hashicorp/hcl/v2/hcl#BodySchema )

	// fix any ConfigModeAttr blocks present from legacy providers
	body = blocktoattr.FixUpBlockAttrs(body, schema)

	// Use the low-level schema with the body to decode one level We'll just
	// ignore any additional content that's not covered by the schema, which
	// will effectively ignore "dynamic" blocks, and may also ignore other
	// unknown stuff but anything else would get flagged by Terraform as an
	// error anyway, and so we wouldn't end up in here.
	content, _, _ := body.PartialContent(lowSchema)
	if content == nil {
		// Should never happen for a valid body, but we'll just generate empty
		// if there were any problems.
		return nil
	}

	ret := make(expressions)

	// Any attributes we encode directly as expression objects.
	for name, attr := range content.Attributes {
		ret[name] = marshalExpression(attr.Expr) // note: singular expression for this one
	}

	// Any nested blocks require a recursive call to produce nested expressions
	// objects.
	for _, block := range content.Blocks {
		typeName := block.Type
		blockS, exists := schema.BlockTypes[typeName]
		if !exists {
			// Should never happen since only block types in the schema would be
			// put in blocks list
			continue
		}

		switch blockS.Nesting {
		case configschema.NestingSingle, configschema.NestingGroup:
			ret[typeName] = marshalExpressions(block.Body, &blockS.Block)
		case configschema.NestingList, configschema.NestingSet:
			if _, exists := ret[typeName]; !exists {
				ret[typeName] = make([]map[string]interface{}, 0, 1)
			}
			ret[typeName] = append(ret[typeName].([]map[string]interface{}), marshalExpressions(block.Body, &blockS.Block))
		case configschema.NestingMap:
			if _, exists := ret[typeName]; !exists {
				ret[typeName] = make(map[string]map[string]interface{})
			}
			// NestingMap blocks always have the key in the first (and only) label
			key := block.Labels[0]
			retMap := ret[typeName].(map[string]map[string]interface{})
			retMap[key] = marshalExpressions(block.Body, &blockS.Block)
		}
	}

	return ret
}

// traversalStr produces a representation of an HCL traversal that is compact,
// resembles HCL native syntax, and is suitable for display in the UI.
//
// This was copied (and simplified) from internal/command/views/json/diagnostic.go.
func traversalStr(traversal hcl.Traversal) string {
	var buf bytes.Buffer
	for _, step := range traversal {
		switch tStep := step.(type) {
		case hcl.TraverseRoot:
			buf.WriteString(tStep.Name)
		case hcl.TraverseAttr:
			buf.WriteByte('.')
			buf.WriteString(tStep.Name)
		case hcl.TraverseIndex:
			buf.WriteByte('[')
			switch tStep.Key.Type() {
			case cty.String:
				buf.WriteString(fmt.Sprintf("%q", tStep.Key.AsString()))
			case cty.Number:
				bf := tStep.Key.AsBigFloat()
				buf.WriteString(bf.Text('g', 10))
			}
			buf.WriteByte(']')
		}
	}
	return buf.String()
}
