package tfdiags

import "fmt"

// ConsolidateWarnings checks if there is an unreasonable amount of warnings
// with the same summary in the receiver and, if so, returns a new diagnostics
// with some of those warnings consolidated into a single warning in order
// to reduce the verbosity of the output.
//
// This mechanism is here primarily for diagnostics printed out at the CLI. In
// other contexts it is likely better to just return the warnings directly,
// particularly if they are going to be interpreted by software rather than
// by a human reader.
//
// The returned slice always has a separate backing array from the reciever,
// but some diagnostic values themselves might be shared.
//
// The definition of "unreasonable" is given as the threshold argument. At most
// that many warnings with the same summary will be shown.
func (diags Diagnostics) ConsolidateWarnings(threshold int) Diagnostics {
	if len(diags) == 0 {
		return nil
	}

	newDiags := make(Diagnostics, 0, len(diags))

	// We'll track how many times we've seen each warning summary so we can
	// decide when to start consolidating. Once we _have_ started consolidating,
	// we'll also track the object representing the consolidated warning
	// so we can continue appending to it.
	warningStats := make(map[string]int)
	warningGroups := make(map[string]*warningGroup)

	for _, diag := range diags {
		severity := diag.Severity()
		if severity != Warning || diag.Source().Subject == nil {
			// Only warnings can get special treatment, and we only
			// consolidate warnings that have source locations because
			// our primary goal here is to deal with the situation where
			// some configuration language feature is producing a warning
			// each time it's used across a potentially-large config.
			newDiags = newDiags.Append(diag)
			continue
		}

		desc := diag.Description()
		summary := desc.Summary
		if g, ok := warningGroups[summary]; ok {
			// We're already grouping this one, so we'll just continue it.
			g.Append(diag)
			continue
		}

		warningStats[summary]++
		if warningStats[summary] == threshold {
			// Initially creating the group doesn't really change anything
			// visibly in the result, since a group with only one warning
			// is just a passthrough anyway, but once we do this any additional
			// warnings with the same summary will get appended to this group.
			g := &warningGroup{}
			newDiags = newDiags.Append(g)
			warningGroups[summary] = g
			g.Append(diag)
			continue
		}

		// If this warning is not consolidating yet then we'll just append
		// it directly.
		newDiags = newDiags.Append(diag)
	}

	return newDiags
}

// A warningGroup is one or more warning diagnostics grouped together for
// UI consolidation purposes.
//
// A warningGroup with only one diagnostic in it is just a passthrough for
// that one diagnostic. If it has more than one then it will behave mostly
// like the first one but its detail message will include an additional
// sentence mentioning the consolidation. A warningGroup with no diagnostics
// at all is invalid and will panic when used.
type warningGroup struct {
	Warnings Diagnostics
}

var _ Diagnostic = (*warningGroup)(nil)

func (wg *warningGroup) Severity() Severity {
	return wg.Warnings[0].Severity()
}

func (wg *warningGroup) Description() Description {
	desc := wg.Warnings[0].Description()
	if len(wg.Warnings) < 2 {
		return desc
	}
	extraCount := len(wg.Warnings) - 1
	var msg string
	switch extraCount {
	case 1:
		msg = "(and one more similar warning elsewhere)"
	default:
		msg = fmt.Sprintf("(and %d more similar warnings elsewhere)", extraCount)
	}
	if desc.Detail != "" {
		desc.Detail = desc.Detail + "\n\n" + msg
	} else {
		desc.Detail = msg
	}
	return desc
}

func (wg *warningGroup) Source() Source {
	return wg.Warnings[0].Source()
}

func (wg *warningGroup) FromExpr() *FromExpr {
	return wg.Warnings[0].FromExpr()
}

func (wg *warningGroup) ExtraInfo() interface{} {
	return wg.Warnings[0].ExtraInfo()
}

func (wg *warningGroup) Append(diag Diagnostic) {
	if diag.Severity() != Warning {
		panic("can't append a non-warning diagnostic to a warningGroup")
	}
	wg.Warnings = append(wg.Warnings, diag)
}

// WarningGroupSourceRanges can be used in conjunction with
// Diagnostics.ConsolidateWarnings to recover the full set of original source
// locations from a consolidated warning.
//
// For convenience, this function accepts any diagnostic and will just return
// the single Source value from any diagnostic that isn't a warning group.
func WarningGroupSourceRanges(diag Diagnostic) []Source {
	wg, ok := diag.(*warningGroup)
	if !ok {
		return []Source{diag.Source()}
	}

	ret := make([]Source, len(wg.Warnings))
	for i, wrappedDiag := range wg.Warnings {
		ret[i] = wrappedDiag.Source()
	}
	return ret
}
