package hcl

import (
	"fmt"
)

// MergeFiles combines the given files to produce a single body that contains
// configuration from all of the given files.
//
// The ordering of the given files decides the order in which contained
// elements will be returned. If any top-level attributes are defined with
// the same name across multiple files, a diagnostic will be produced from
// the Content and PartialContent methods describing this error in a
// user-friendly way.
func MergeFiles(files []*File) Body {
	var bodies []Body
	for _, file := range files {
		bodies = append(bodies, file.Body)
	}
	return MergeBodies(bodies)
}

// MergeBodies is like MergeFiles except it deals directly with bodies, rather
// than with entire files.
func MergeBodies(bodies []Body) Body {
	if len(bodies) == 0 {
		// Swap out for our singleton empty body, to reduce the number of
		// empty slices we have hanging around.
		return emptyBody
	}

	// If any of the given bodies are already merged bodies, we'll unpack
	// to flatten to a single mergedBodies, since that's conceptually simpler.
	// This also, as a side-effect, eliminates any empty bodies, since
	// empties are merged bodies with no inner bodies.
	var newLen int
	var flatten bool
	for _, body := range bodies {
		if children, merged := body.(mergedBodies); merged {
			newLen += len(children)
			flatten = true
		} else {
			newLen++
		}
	}

	if !flatten { // not just newLen == len, because we might have mergedBodies with single bodies inside
		return mergedBodies(bodies)
	}

	if newLen == 0 {
		// Don't allocate a new empty when we already have one
		return emptyBody
	}

	new := make([]Body, 0, newLen)
	for _, body := range bodies {
		if children, merged := body.(mergedBodies); merged {
			new = append(new, children...)
		} else {
			new = append(new, body)
		}
	}
	return mergedBodies(new)
}

var emptyBody = mergedBodies([]Body{})

// EmptyBody returns a body with no content. This body can be used as a
// placeholder when a body is required but no body content is available.
func EmptyBody() Body {
	return emptyBody
}

type mergedBodies []Body

// Content returns the content produced by applying the given schema to all
// of the merged bodies and merging the result.
//
// Although required attributes _are_ supported, they should be used sparingly
// with merged bodies since in this case there is no contextual information
// with which to return good diagnostics. Applications working with merged
// bodies may wish to mark all attributes as optional and then check for
// required attributes afterwards, to produce better diagnostics.
func (mb mergedBodies) Content(schema *BodySchema) (*BodyContent, Diagnostics) {
	// the returned body will always be empty in this case, because mergedContent
	// will only ever call Content on the child bodies.
	content, _, diags := mb.mergedContent(schema, false)
	return content, diags
}

func (mb mergedBodies) PartialContent(schema *BodySchema) (*BodyContent, Body, Diagnostics) {
	return mb.mergedContent(schema, true)
}

func (mb mergedBodies) JustAttributes() (Attributes, Diagnostics) {
	attrs := make(map[string]*Attribute)
	var diags Diagnostics

	for _, body := range mb {
		thisAttrs, thisDiags := body.JustAttributes()

		if len(thisDiags) != 0 {
			diags = append(diags, thisDiags...)
		}

		if thisAttrs != nil {
			for name, attr := range thisAttrs {
				if existing := attrs[name]; existing != nil {
					diags = diags.Append(&Diagnostic{
						Severity: DiagError,
						Summary:  "Duplicate argument",
						Detail: fmt.Sprintf(
							"Argument %q was already set at %s",
							name, existing.NameRange.String(),
						),
						Subject: &attr.NameRange,
					})
					continue
				}

				attrs[name] = attr
			}
		}
	}

	return attrs, diags
}

func (mb mergedBodies) MissingItemRange() Range {
	if len(mb) == 0 {
		// Nothing useful to return here, so we'll return some garbage.
		return Range{
			Filename: "<empty>",
		}
	}

	// arbitrarily use the first body's missing item range
	return mb[0].MissingItemRange()
}

func (mb mergedBodies) mergedContent(schema *BodySchema, partial bool) (*BodyContent, Body, Diagnostics) {
	// We need to produce a new schema with none of the attributes marked as
	// required, since _any one_ of our bodies can contribute an attribute value.
	// We'll separately check that all required attributes are present at
	// the end.
	mergedSchema := &BodySchema{
		Blocks: schema.Blocks,
	}
	for _, attrS := range schema.Attributes {
		mergedAttrS := attrS
		mergedAttrS.Required = false
		mergedSchema.Attributes = append(mergedSchema.Attributes, mergedAttrS)
	}

	var mergedLeftovers []Body
	content := &BodyContent{
		Attributes: map[string]*Attribute{},
	}

	var diags Diagnostics
	for _, body := range mb {
		var thisContent *BodyContent
		var thisLeftovers Body
		var thisDiags Diagnostics

		if partial {
			thisContent, thisLeftovers, thisDiags = body.PartialContent(mergedSchema)
		} else {
			thisContent, thisDiags = body.Content(mergedSchema)
		}

		if thisLeftovers != nil {
			mergedLeftovers = append(mergedLeftovers, thisLeftovers)
		}
		if len(thisDiags) != 0 {
			diags = append(diags, thisDiags...)
		}

		if thisContent.Attributes != nil {
			for name, attr := range thisContent.Attributes {
				if existing := content.Attributes[name]; existing != nil {
					diags = diags.Append(&Diagnostic{
						Severity: DiagError,
						Summary:  "Duplicate argument",
						Detail: fmt.Sprintf(
							"Argument %q was already set at %s",
							name, existing.NameRange.String(),
						),
						Subject: &attr.NameRange,
					})
					continue
				}
				content.Attributes[name] = attr
			}
		}

		if len(thisContent.Blocks) != 0 {
			content.Blocks = append(content.Blocks, thisContent.Blocks...)
		}
	}

	// Finally, we check for required attributes.
	for _, attrS := range schema.Attributes {
		if !attrS.Required {
			continue
		}

		if content.Attributes[attrS.Name] == nil {
			// We don't have any context here to produce a good diagnostic,
			// which is why we warn in the Content docstring to minimize the
			// use of required attributes on merged bodies.
			diags = diags.Append(&Diagnostic{
				Severity: DiagError,
				Summary:  "Missing required argument",
				Detail: fmt.Sprintf(
					"The argument %q is required, but was not set.",
					attrS.Name,
				),
			})
		}
	}

	leftoverBody := MergeBodies(mergedLeftovers)
	return content, leftoverBody, diags
}
