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

package moduledeps

import (
	"sort"
	"strings"

	"github.com/hashicorp/terraform/internal/plugin/discovery"
)

// Module represents the dependencies of a single module, as well being
// a node in a tree of such structures representing the dependencies of
// an entire configuration.
type Module struct {
	Name      string
	Providers Providers
	Children  []*Module
}

// WalkFunc is a callback type for use with Module.WalkTree
type WalkFunc func(path []string, parent *Module, current *Module) error

// WalkTree calls the given callback once for the receiver and then
// once for each descendent, in an order such that parents are called
// before their children and siblings are called in the order they
// appear in the Children slice.
//
// When calling the callback, parent will be nil for the first call
// for the receiving module, and then set to the direct parent of
// each module for the subsequent calls.
//
// The path given to the callback is valid only until the callback
// returns, after which it will be mutated and reused. Callbacks must
// therefore copy the path slice if they wish to retain it.
//
// If the given callback returns an error, the walk will be aborted at
// that point and that error returned to the caller.
//
// This function is not thread-safe for concurrent modifications of the
// data structure, so it's the caller's responsibility to arrange for that
// should it be needed.
//
// It is safe for a callback to modify the descendents of the "current"
// module, including the ordering of the Children slice itself, but the
// callback MUST NOT modify the parent module.
func (m *Module) WalkTree(cb WalkFunc) error {
	return walkModuleTree(make([]string, 0, 1), nil, m, cb)
}

func walkModuleTree(path []string, parent *Module, current *Module, cb WalkFunc) error {
	path = append(path, current.Name)
	err := cb(path, parent, current)
	if err != nil {
		return err
	}

	for _, child := range current.Children {
		err := walkModuleTree(path, current, child, cb)
		if err != nil {
			return err
		}
	}
	return nil
}

// SortChildren sorts the Children slice into lexicographic order by
// name, in-place.
//
// This is primarily useful prior to calling WalkTree so that the walk
// will proceed in a consistent order.
func (m *Module) SortChildren() {
	sort.Sort(sortModules{m.Children})
}

// SortDescendents is a convenience wrapper for calling SortChildren on
// the receiver and all of its descendent modules.
func (m *Module) SortDescendents() {
	m.WalkTree(func(path []string, parent *Module, current *Module) error {
		current.SortChildren()
		return nil
	})
}

type sortModules struct {
	modules []*Module
}

func (s sortModules) Len() int {
	return len(s.modules)
}

func (s sortModules) Less(i, j int) bool {
	cmp := strings.Compare(s.modules[i].Name, s.modules[j].Name)
	return cmp < 0
}

func (s sortModules) Swap(i, j int) {
	s.modules[i], s.modules[j] = s.modules[j], s.modules[i]
}

// ProviderRequirements produces a PluginRequirements structure that can
// be used with discovery.PluginMetaSet.ConstrainVersions to identify
// suitable plugins to satisfy the module's provider dependencies.
//
// This method only considers the direct requirements of the receiver.
// Use AllPluginRequirements to flatten the dependencies for the
// entire tree of modules.
//
// Requirements returned by this method include only version constraints,
// and apply no particular SHA256 hash constraint.
func (m *Module) ProviderRequirements() discovery.PluginRequirements {
	ret := make(discovery.PluginRequirements)
	for pFqn, dep := range m.Providers {
		providerType := pFqn.Type
		if existing, exists := ret[providerType]; exists {
			ret[providerType].Versions = existing.Versions.Append(dep.Constraints)
		} else {
			ret[providerType] = &discovery.PluginConstraints{
				Versions: dep.Constraints,
			}
		}
	}
	return ret
}

// AllProviderRequirements calls ProviderRequirements for the receiver and all
// of its descendents, and merges the result into a single PluginRequirements
// structure that would satisfy all of the modules together.
//
// Requirements returned by this method include only version constraints,
// and apply no particular SHA256 hash constraint.
func (m *Module) AllProviderRequirements() discovery.PluginRequirements {
	var ret discovery.PluginRequirements
	m.WalkTree(func(path []string, parent *Module, current *Module) error {
		ret = ret.Merge(current.ProviderRequirements())
		return nil
	})
	return ret
}

// Equal returns true if the receiver is the root of an identical tree
// to the other given Module. This is a deep comparison that considers
// the equality of all downstream modules too.
//
// The children are considered to be ordered, so callers may wish to use
// SortDescendents first to normalize the order of the slices of child nodes.
//
// The implementation of this function is not optimized since it is provided
// primarily for use in tests.
func (m *Module) Equal(other *Module) bool {
	// take care of nils first
	if m == nil && other == nil {
		return true
	} else if (m == nil && other != nil) || (m != nil && other == nil) {
		return false
	}

	if m.Name != other.Name {
		return false
	}

	if len(m.Providers) != len(other.Providers) {
		return false
	}
	if len(m.Children) != len(other.Children) {
		return false
	}

	// Can't use reflect.DeepEqual on this provider structure because
	// the nested Constraints objects contain function pointers that
	// never compare as equal. So we'll need to walk it the long way.
	for inst, dep := range m.Providers {
		if _, exists := other.Providers[inst]; !exists {
			return false
		}

		if dep.Reason != other.Providers[inst].Reason {
			return false
		}

		// Constraints are not too easy to compare robustly, so
		// we'll just use their string representations as a proxy
		// for now.
		if dep.Constraints.String() != other.Providers[inst].Constraints.String() {
			return false
		}
	}

	// Above we already checked that we have the same number of children
	// in each module, so now we just need to check that they are
	// recursively equal.
	for i := range m.Children {
		if !m.Children[i].Equal(other.Children[i]) {
			return false
		}
	}

	// If we fall out here then they are equal
	return true
}
