package terraform

import (
	"log"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/dag"
	"github.com/hashicorp/terraform/internal/lang"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

type ConcreteModuleNodeFunc func(n *nodeExpandModule) dag.Vertex

// nodeExpandModule represents a module call in the configuration that
// might expand into multiple module instances depending on how it is
// configured.
type nodeExpandModule struct {
	Addr       addrs.Module
	Config     *configs.Module
	ModuleCall *configs.ModuleCall
}

var (
	_ GraphNodeExecutable       = (*nodeExpandModule)(nil)
	_ GraphNodeReferencer       = (*nodeExpandModule)(nil)
	_ GraphNodeReferenceOutside = (*nodeExpandModule)(nil)
	_ graphNodeExpandsInstances = (*nodeExpandModule)(nil)
)

func (n *nodeExpandModule) expandsInstances() {}

func (n *nodeExpandModule) Name() string {
	return n.Addr.String() + " (expand)"
}

// GraphNodeModulePath implementation
func (n *nodeExpandModule) ModulePath() addrs.Module {
	return n.Addr
}

// GraphNodeReferencer implementation
func (n *nodeExpandModule) References() []*addrs.Reference {
	var refs []*addrs.Reference

	if n.ModuleCall == nil {
		return nil
	}

	refs = append(refs, n.DependsOn()...)

	// Expansion only uses the count and for_each expressions, so this
	// particular graph node only refers to those.
	// Individual variable values in the module call definition might also
	// refer to other objects, but that's handled by
	// NodeApplyableModuleVariable.
	//
	// Because our Path method returns the module instance that contains
	// our call, these references will be correctly interpreted as being
	// in the calling module's namespace, not the namespaces of any of the
	// child module instances we might expand to during our evaluation.

	if n.ModuleCall.Count != nil {
		countRefs, _ := lang.ReferencesInExpr(n.ModuleCall.Count)
		refs = append(refs, countRefs...)
	}
	if n.ModuleCall.ForEach != nil {
		forEachRefs, _ := lang.ReferencesInExpr(n.ModuleCall.ForEach)
		refs = append(refs, forEachRefs...)
	}
	return refs
}

func (n *nodeExpandModule) DependsOn() []*addrs.Reference {
	if n.ModuleCall == nil {
		return nil
	}

	var refs []*addrs.Reference
	for _, traversal := range n.ModuleCall.DependsOn {
		ref, diags := addrs.ParseRef(traversal)
		if diags.HasErrors() {
			// We ignore this here, because this isn't a suitable place to return
			// errors. This situation should be caught and rejected during
			// validation.
			log.Printf("[ERROR] Can't parse %#v from depends_on as reference: %s", traversal, diags.Err())
			continue
		}

		refs = append(refs, ref)
	}

	return refs
}

// GraphNodeReferenceOutside
func (n *nodeExpandModule) ReferenceOutside() (selfPath, referencePath addrs.Module) {
	return n.Addr, n.Addr.Parent()
}

// GraphNodeExecutable
func (n *nodeExpandModule) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
	expander := ctx.InstanceExpander()
	_, call := n.Addr.Call()

	// nodeExpandModule itself does not have visibility into how its ancestors
	// were expanded, so we use the expander here to provide all possible paths
	// to our module, and register module instances with each of them.
	for _, module := range expander.ExpandModule(n.Addr.Parent()) {
		ctx = ctx.WithPath(module)
		switch {
		case n.ModuleCall.Count != nil:
			count, ctDiags := evaluateCountExpression(n.ModuleCall.Count, ctx)
			diags = diags.Append(ctDiags)
			if diags.HasErrors() {
				return diags
			}
			expander.SetModuleCount(module, call, count)

		case n.ModuleCall.ForEach != nil:
			forEach, feDiags := evaluateForEachExpression(n.ModuleCall.ForEach, ctx)
			diags = diags.Append(feDiags)
			if diags.HasErrors() {
				return diags
			}
			expander.SetModuleForEach(module, call, forEach)

		default:
			expander.SetModuleSingle(module, call)
		}
	}

	return diags

}

// nodeCloseModule represents an expanded module during apply, and is visited
// after all other module instance nodes. This node will depend on all module
// instance resource and outputs, and anything depending on the module should
// wait on this node.
// Besides providing a root node for dependency ordering, nodeCloseModule also
// cleans up state after all the module nodes have been evaluated, removing
// empty resources and modules from the state.
// The root module instance also closes any remaining provisioner plugins which
// do not have a lifecycle controlled by individual graph nodes.
type nodeCloseModule struct {
	Addr addrs.Module
}

var (
	_ GraphNodeReferenceable    = (*nodeCloseModule)(nil)
	_ GraphNodeReferenceOutside = (*nodeCloseModule)(nil)
	_ GraphNodeExecutable       = (*nodeCloseModule)(nil)
)

func (n *nodeCloseModule) ModulePath() addrs.Module {
	return n.Addr
}

func (n *nodeCloseModule) ReferenceOutside() (selfPath, referencePath addrs.Module) {
	return n.Addr.Parent(), n.Addr
}

func (n *nodeCloseModule) ReferenceableAddrs() []addrs.Referenceable {
	_, call := n.Addr.Call()
	return []addrs.Referenceable{
		call,
	}
}

func (n *nodeCloseModule) Name() string {
	if len(n.Addr) == 0 {
		return "root"
	}
	return n.Addr.String() + " (close)"
}

func (n *nodeCloseModule) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
	if !n.Addr.IsRoot() {
		return
	}

	// If this is the root module, we are cleaning up the walk, so close
	// any running provisioners
	diags = diags.Append(ctx.CloseProvisioners())

	switch op {
	case walkApply, walkDestroy:
		state := ctx.State().Lock()
		defer ctx.State().Unlock()

		for modKey, mod := range state.Modules {
			// clean out any empty resources
			for resKey, res := range mod.Resources {
				if len(res.Instances) == 0 {
					delete(mod.Resources, resKey)
				}
			}

			// empty child modules are always removed
			if len(mod.Resources) == 0 && !mod.Addr.IsRoot() {
				delete(state.Modules, modKey)
			}
		}
		return nil
	default:
		return nil
	}
}

// nodeValidateModule wraps a nodeExpand module for validation, ensuring that
// no expansion is attempted during evaluation, when count and for_each
// expressions may not be known.
type nodeValidateModule struct {
	nodeExpandModule
}

var _ GraphNodeExecutable = (*nodeValidateModule)(nil)

// GraphNodeEvalable
func (n *nodeValidateModule) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
	_, call := n.Addr.Call()
	expander := ctx.InstanceExpander()

	// Modules all evaluate to single instances during validation, only to
	// create a proper context within which to evaluate. All parent modules
	// will be a single instance, but still get our address in the expected
	// manner anyway to ensure they've been registered correctly.
	for _, module := range expander.ExpandModule(n.Addr.Parent()) {
		ctx = ctx.WithPath(module)

		// Validate our for_each and count expressions at a basic level
		// We skip validation on known, because there will be unknown values before
		// a full expansion, presuming these errors will be caught in later steps
		switch {
		case n.ModuleCall.Count != nil:
			_, countDiags := evaluateCountExpressionValue(n.ModuleCall.Count, ctx)
			diags = diags.Append(countDiags)

		case n.ModuleCall.ForEach != nil:
			_, forEachDiags := evaluateForEachExpressionValue(n.ModuleCall.ForEach, ctx, true)
			diags = diags.Append(forEachDiags)
		}

		diags = diags.Append(validateDependsOn(ctx, n.ModuleCall.DependsOn))

		// now set our own mode to single
		expander.SetModuleSingle(module, call)
	}

	return diags
}
