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
}
