package parser

import "google3/third_party/golang/hashicorp/hcl/hcl/ast/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
}
