// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package structured

import (
	"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
)

// ChangeMap is a Change that represents a Map or an Object type, and has
// converted the relevant interfaces into maps for easier access.
type ChangeMap struct {
	// Before contains the value before the proposed change.
	Before map[string]interface{}

	// After contains the value after the proposed change.
	After map[string]interface{}

	// Unknown contains the unknown status of any elements/attributes of this
	// map/object.
	Unknown map[string]interface{}

	// BeforeSensitive contains the before sensitive status of any
	// elements/attributes of this map/object.
	BeforeSensitive map[string]interface{}

	// AfterSensitive contains the after sensitive status of any
	// elements/attributes of this map/object.
	AfterSensitive map[string]interface{}

	// ReplacePaths matches the same attributes in Change exactly.
	ReplacePaths attribute_path.Matcher

	// RelevantAttributes matches the same attributes in Change exactly.
	RelevantAttributes attribute_path.Matcher
}

// AsMap converts the Change into an object or map representation by converting
// the internal Before, After, Unknown, BeforeSensitive, and AfterSensitive
// data structures into generic maps.
func (change Change) AsMap() ChangeMap {
	return ChangeMap{
		Before:             genericToMap(change.Before),
		After:              genericToMap(change.After),
		Unknown:            genericToMap(change.Unknown),
		BeforeSensitive:    genericToMap(change.BeforeSensitive),
		AfterSensitive:     genericToMap(change.AfterSensitive),
		ReplacePaths:       change.ReplacePaths,
		RelevantAttributes: change.RelevantAttributes,
	}
}

// GetChild safely packages up a Change object for the given child, handling
// all the cases where the data might be null or a static boolean.
func (m ChangeMap) GetChild(key string) Change {
	before, beforeExplicit := getFromGenericMap(m.Before, key)
	after, afterExplicit := getFromGenericMap(m.After, key)
	unknown, _ := getFromGenericMap(m.Unknown, key)
	beforeSensitive, _ := getFromGenericMap(m.BeforeSensitive, key)
	afterSensitive, _ := getFromGenericMap(m.AfterSensitive, key)

	return Change{
		BeforeExplicit:     beforeExplicit,
		AfterExplicit:      afterExplicit,
		Before:             before,
		After:              after,
		Unknown:            unknown,
		BeforeSensitive:    beforeSensitive,
		AfterSensitive:     afterSensitive,
		ReplacePaths:       m.ReplacePaths.GetChildWithKey(key),
		RelevantAttributes: m.RelevantAttributes.GetChildWithKey(key),
	}
}

// ExplicitKeys returns the keys in the Before and After, as opposed to AllKeys
// which also includes keys from the additional meta structures (like the
// sensitive and unknown values).
//
// This function is useful for processing nested attributes and repeated blocks
// where the unknown and sensitive structs contain information about the actual
// attributes, while the before and after structs hold the actual nested values.
func (m ChangeMap) ExplicitKeys() []string {
	keys := make(map[string]bool)
	for before := range m.Before {
		if _, ok := keys[before]; ok {
			continue
		}
		keys[before] = true
	}
	for after := range m.After {
		if _, ok := keys[after]; ok {
			continue
		}
		keys[after] = true
	}

	var dedupedKeys []string
	for key := range keys {
		dedupedKeys = append(dedupedKeys, key)
	}
	return dedupedKeys
}

// AllKeys returns all the possible keys for this map. The keys for the map are
// potentially hidden and spread across multiple internal data structures and
// so this function conveniently packages them up.
func (m ChangeMap) AllKeys() []string {
	keys := make(map[string]bool)
	for before := range m.Before {
		if _, ok := keys[before]; ok {
			continue
		}
		keys[before] = true
	}
	for after := range m.After {
		if _, ok := keys[after]; ok {
			continue
		}
		keys[after] = true
	}
	for unknown := range m.Unknown {
		if _, ok := keys[unknown]; ok {
			continue
		}
		keys[unknown] = true
	}
	for sensitive := range m.AfterSensitive {
		if _, ok := keys[sensitive]; ok {
			continue
		}
		keys[sensitive] = true
	}
	for sensitive := range m.BeforeSensitive {
		if _, ok := keys[sensitive]; ok {
			continue
		}
		keys[sensitive] = true
	}

	var dedupedKeys []string
	for key := range keys {
		dedupedKeys = append(dedupedKeys, key)
	}
	return dedupedKeys
}

func getFromGenericMap(generic map[string]interface{}, key string) (interface{}, bool) {
	if generic == nil {
		return nil, false
	}

	if child, ok := generic[key]; ok {
		return child, ok
	}
	return nil, false
}

func genericToMap(generic interface{}) map[string]interface{} {
	if concrete, ok := generic.(map[string]interface{}); ok {
		return concrete
	}
	return nil
}
