package parser

import "github.com/hashicorp/hcl/hcl/ast"

// flattenObjects takes an AST node, walks it, and flattens
func flattenObjects(node ast.Node) {
	ast.Walk(node, func(n ast.Node) (ast.Node, bool) {
		// We only care about lists, because this is what we modify
		list, ok := n.(*ast.ObjectList)
		if !ok {
			return n, true
		}

		// Rebuild the item list
		items := make([]*ast.ObjectItem, 0, len(list.Items))
		frontier := make([]*ast.ObjectItem, len(list.Items))
		copy(frontier, list.Items)
		for len(frontier) > 0 {
			// Pop the current item
			n := len(frontier)
			item := frontier[n-1]
			frontier = frontier[:n-1]

			switch v := item.Val.(type) {
			case *ast.ObjectType:
				items, frontier = flattenObjectType(v, item, items, frontier)
			case *ast.ListType:
				items, frontier = flattenListType(v, item, items, frontier)
			default:
				items = append(items, item)
			}
		}

		// Reverse the list since the frontier model runs things backwards
		for i := len(items)/2 - 1; i >= 0; i-- {
			opp := len(items) - 1 - i
			items[i], items[opp] = items[opp], items[i]
		}

		// Done! Set the original items
		list.Items = items
		return n, true
	})
}

func flattenListType(
	ot *ast.ListType,
	item *ast.ObjectItem,
	items []*ast.ObjectItem,
	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
	// If the list is empty, keep the original list
	if len(ot.List) == 0 {
		items = append(items, item)
		return items, frontier
	}

	// All the elements of this object must also be objects!
	for _, subitem := range ot.List {
		if _, ok := subitem.(*ast.ObjectType); !ok {
			items = append(items, item)
			return items, frontier
		}
	}

	// Great! We have a match go through all the items and flatten
	for _, elem := range ot.List {
		// Add it to the frontier so that we can recurse
		frontier = append(frontier, &ast.ObjectItem{
			Keys:        item.Keys,
			Assign:      item.Assign,
			Val:         elem,
			LeadComment: item.LeadComment,
			LineComment: item.LineComment,
		})
	}

	return items, frontier
}

func flattenObjectType(
	ot *ast.ObjectType,
	item *ast.ObjectItem,
	items []*ast.ObjectItem,
	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
	// If the list has no items we do not have to flatten anything
	if ot.List.Items == nil {
		items = append(items, item)
		return items, frontier
	}

	// All the elements of this object must also be objects!
	for _, subitem := range ot.List.Items {
		if _, ok := subitem.Val.(*ast.ObjectType); !ok {
			items = append(items, item)
			return items, frontier
		}
	}

	// Great! We have a match go through all the items and flatten
	for _, subitem := range ot.List.Items {
		// Copy the new key
		keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys))
		copy(keys, item.Keys)
		copy(keys[len(item.Keys):], subitem.Keys)

		// Add it to the frontier so that we can recurse
		frontier = append(frontier, &ast.ObjectItem{
			Keys:        keys,
			Assign:      item.Assign,
			Val:         subitem.Val,
			LeadComment: item.LeadComment,
			LineComment: item.LineComment,
		})
	}

	return items, frontier
}
