// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package interpreter

import (
	"fmt"
	"strings"

	"cel.dev/cel-go/common/containers"
	"cel.dev/cel-go/common/types"
	"cel.dev/cel-go/common/types/ref"
)

// AttributePattern represents a top-level variable with an optional set of qualifier patterns.
//
// When using a CEL expression within a container, e.g. a package or namespace, the variable name
// in the pattern must match the qualified name produced during the variable namespace resolution.
// For example, if variable `c` appears in an expression whose container is `a.b`, the variable
// name supplied to the pattern must be `a.b.c`
//
// The qualifier patterns for attribute matching must be one of the following:
//
//   - valid map key type: string, int, uint, bool
//   - wildcard (*)
//
// Examples:
//
//  1. ns.myvar["complex-value"]
//  2. ns.myvar["complex-value"][0]
//  3. ns.myvar["complex-value"].*.name
//
// The first example is simple: match an attribute where the variable is 'ns.myvar' with a
// field access on 'complex-value'. The second example expands the match to indicate that only
// a specific index `0` should match. And lastly, the third example matches any indexed access
// that later selects the 'name' field.
type AttributePattern struct {
	variable          string
	qualifierPatterns []*AttributeQualifierPattern
}

// NewAttributePattern produces a new mutable AttributePattern based on a variable name.
func NewAttributePattern(variable string) *AttributePattern {
	return &AttributePattern{
		variable:          variable,
		qualifierPatterns: []*AttributeQualifierPattern{},
	}
}

// QualString adds a string qualifier pattern to the AttributePattern. The string may be a valid
// identifier, or string map key including empty string.
func (apat *AttributePattern) QualString(pattern string) *AttributePattern {
	apat.qualifierPatterns = append(apat.qualifierPatterns,
		&AttributeQualifierPattern{value: pattern})
	return apat
}

// QualInt adds an int qualifier pattern to the AttributePattern. The index may be either a map or
// list index.
func (apat *AttributePattern) QualInt(pattern int64) *AttributePattern {
	apat.qualifierPatterns = append(apat.qualifierPatterns,
		&AttributeQualifierPattern{value: pattern})
	return apat
}

// QualUint adds an uint qualifier pattern for a map index operation to the AttributePattern.
func (apat *AttributePattern) QualUint(pattern uint64) *AttributePattern {
	apat.qualifierPatterns = append(apat.qualifierPatterns,
		&AttributeQualifierPattern{value: pattern})
	return apat
}

// QualBool adds a bool qualifier pattern for a map index operation to the AttributePattern.
func (apat *AttributePattern) QualBool(pattern bool) *AttributePattern {
	apat.qualifierPatterns = append(apat.qualifierPatterns,
		&AttributeQualifierPattern{value: pattern})
	return apat
}

// Wildcard adds a special sentinel qualifier pattern that will match any single qualifier.
func (apat *AttributePattern) Wildcard() *AttributePattern {
	apat.qualifierPatterns = append(apat.qualifierPatterns,
		&AttributeQualifierPattern{wildcard: true})
	return apat
}

// VariableMatches returns true if the fully qualified variable matches the AttributePattern
// fully qualified variable name.
func (apat *AttributePattern) VariableMatches(variable string) bool {
	return apat.variable == variable
}

// QualifierPatterns returns the set of AttributeQualifierPattern values on the AttributePattern.
func (apat *AttributePattern) QualifierPatterns() []*AttributeQualifierPattern {
	return apat.qualifierPatterns
}

// AttributeQualifierPattern holds a wildcard or valued qualifier pattern.
type AttributeQualifierPattern struct {
	wildcard bool
	value    any
}

// Matches returns true if the qualifier pattern is a wildcard, or the Qualifier implements the
// qualifierValueEquator interface and its IsValueEqualTo returns true for the qualifier pattern.
func (qpat *AttributeQualifierPattern) Matches(q Qualifier) bool {
	if qpat.wildcard {
		return true
	}
	qve, ok := q.(qualifierValueEquator)
	return ok && qve.QualifierValueEquals(qpat.value)
}

// qualifierValueEquator defines an interface for determining if an input value, of valid map key
// type, is equal to the value held in the Qualifier. This interface is used by the
// AttributeQualifierPattern to determine pattern matches for non-wildcard qualifier patterns.
//
// Note: Attribute values are also Qualifier values; however, Attributes are resolved before
// qualification happens. This is an implementation detail, but one relevant to why the Attribute
// types do not surface in the list of implementations.
//
// See: partialAttributeFactory.matchesUnknownPatterns for more details on how this interface is
// used.
type qualifierValueEquator interface {
	// QualifierValueEquals returns true if the input value is equal to the value held in the
	// Qualifier.
	QualifierValueEquals(value any) bool
}

// QualifierValueEquals implementation for boolean qualifiers.
func (q *boolQualifier) QualifierValueEquals(value any) bool {
	bval, ok := value.(bool)
	return ok && q.value == bval
}

// QualifierValueEquals implementation for field qualifiers.
func (q *fieldQualifier) QualifierValueEquals(value any) bool {
	sval, ok := value.(string)
	return ok && q.Name == sval
}

// QualifierValueEquals implementation for string qualifiers.
func (q *stringQualifier) QualifierValueEquals(value any) bool {
	sval, ok := value.(string)
	return ok && q.value == sval
}

// QualifierValueEquals implementation for int qualifiers.
func (q *intQualifier) QualifierValueEquals(value any) bool {
	return numericValueEquals(value, q.celValue)
}

// QualifierValueEquals implementation for uint qualifiers.
func (q *uintQualifier) QualifierValueEquals(value any) bool {
	return numericValueEquals(value, q.celValue)
}

// QualifierValueEquals implementation for double qualifiers.
func (q *doubleQualifier) QualifierValueEquals(value any) bool {
	return numericValueEquals(value, q.celValue)
}

// numericValueEquals uses CEL equality to determine whether two number values are
func numericValueEquals(value any, celValue ref.Val) bool {
	val := types.DefaultTypeAdapter.NativeToValue(value)
	return celValue.Equal(val) == types.True
}

// NewPartialAttributeFactory returns an AttributeFactory implementation capable of performing
// AttributePattern matches with PartialActivation inputs.
func NewPartialAttributeFactory(container *containers.Container, adapter types.Adapter, provider types.Provider, opts ...AttrFactoryOption) AttributeFactory {
	fac := NewAttributeFactory(container, adapter, provider, opts...)
	return &partialAttributeFactory{
		AttributeFactory: fac,
		container:        container,
		adapter:          adapter,
		provider:         provider,
	}
}

type partialAttributeFactory struct {
	AttributeFactory
	container *containers.Container
	adapter   types.Adapter
	provider  types.Provider
}

// AbsoluteAttribute implementation of the AttributeFactory interface which wraps the
// NamespacedAttribute resolution in an internal attributeMatcher object to dynamically match
// unknown patterns from PartialActivation inputs if given.
func (fac *partialAttributeFactory) AbsoluteAttribute(id int64, names ...string) NamespacedAttribute {
	attr := fac.AttributeFactory.AbsoluteAttribute(id, names...)
	return &attributeMatcher{fac: fac, NamespacedAttribute: attr}
}

// MaybeAttribute implementation of the AttributeFactory interface which ensure that the set of
// 'maybe' NamespacedAttribute values are produced using the partialAttributeFactory rather than
// the base AttributeFactory implementation.
func (fac *partialAttributeFactory) MaybeAttribute(id int64, name string) Attribute {
	var names []string
	// When there's a single name with a dot prefix, it indicates that the 'maybe' attribute is a
	// globally namespaced identifier.
	if strings.HasPrefix(name, ".") {
		names = append(names, name)
	} else {
		// In all other cases, the candidate names should be inferred.
		names = fac.container.ResolveCandidateNames(name)
	}
	return &maybeAttribute{
		id: id,
		attrs: []NamespacedAttribute{
			fac.AbsoluteAttribute(id, names...),
		},
		adapter:  fac.adapter,
		provider: fac.provider,
		fac:      fac,
	}
}

// matchesUnknownPatterns returns true if the variable names and qualifiers for a given
// Attribute value match any of the ActivationPattern objects in the set of unknown activation
// patterns on the given PartialActivation.
//
// For example, in the expression `a.b`, the Attribute is composed of variable `a`, with string
// qualifier `b`. When a PartialActivation is supplied, it indicates that some or all of the data
// provided in the input is unknown by specifying unknown AttributePatterns. An AttributePattern
// that refers to variable `a` with a string qualifier of `c` will not match `a.b`; however, any
// of the following patterns will match Attribute `a.b`:
//
// - `AttributePattern("a")`
// - `AttributePattern("a").Wildcard()`
// - `AttributePattern("a").QualString("b")`
// - `AttributePattern("a").QualString("b").QualInt(0)`
//
// Any AttributePattern which overlaps an Attribute or vice-versa will produce an Unknown result
// for the last pattern matched variable or qualifier in the Attribute. In the first matching
// example, the expression id representing variable `a` would be listed in the Unknown result,
// whereas in the other pattern examples, the qualifier `b` would be returned as the Unknown.
func (fac *partialAttributeFactory) matchesUnknownPatterns(
	vars PartialActivation,
	attrID int64,
	variableNames []string,
	qualifiers []Qualifier) (*types.Unknown, error) {
	patterns := vars.UnknownAttributePatterns()
	candidateIndices := map[int]struct{}{}
	for _, variable := range variableNames {
		if holder, ok := vars.(localVariableHolder); ok && holder.IsLocalVariable(variable) {
			continue
		}
		for i, pat := range patterns {
			if pat.VariableMatches(variable) {
				if len(qualifiers) == 0 {
					return types.NewUnknown(attrID, types.NewAttributeTrail(variable)), nil
				}
				candidateIndices[i] = struct{}{}
			}
		}
	}
	// Determine whether to return early if there are no candidate unknown patterns.
	if len(candidateIndices) == 0 {
		return nil, nil
	}
	// Resolve the attribute qualifiers into a static set. This prevents more dynamic
	// Attribute resolutions than necessary when there are multiple unknown patterns
	// that traverse the same Attribute-based qualifier field.
	newQuals := make([]Qualifier, len(qualifiers))
	for i, qual := range qualifiers {
		attr, isAttr := qual.(Attribute)
		if isAttr {
			val, err := attr.Resolve(vars)
			if err != nil {
				return nil, err
			}
			// If this resolution behavior ever changes, new implementations of the
			// qualifierValueEquator may be required to handle proper resolution.
			qual, err = fac.NewQualifier(nil, qual.ID(), val, attr.IsOptional())
			if err != nil {
				return nil, err
			}
		}
		newQuals[i] = qual
	}
	// Determine whether any of the unknown patterns match.
	for patIdx := range candidateIndices {
		pat := patterns[patIdx]
		isUnk := true
		matchExprID := attrID
		qualPats := pat.QualifierPatterns()
		for i, qual := range newQuals {
			if i >= len(qualPats) {
				break
			}
			matchExprID = qual.ID()
			qualPat := qualPats[i]
			// Note, the AttributeQualifierPattern relies on the input Qualifier not being an
			// Attribute, since there is no way to resolve the Attribute with the information
			// provided to the Matches call.
			if !qualPat.Matches(qual) {
				isUnk = false
				break
			}
		}
		if isUnk {
			attr := types.NewAttributeTrail(pat.variable)
			for i := 0; i < len(qualPats) && i < len(newQuals); i++ {
				if qual, ok := newQuals[i].(ConstantQualifier); ok {
					switch v := qual.Value().Value().(type) {
					case bool:
						types.QualifyAttribute[bool](attr, v)
					case float64:
						types.QualifyAttribute[int64](attr, int64(v))
					case int64:
						types.QualifyAttribute[int64](attr, v)
					case string:
						types.QualifyAttribute[string](attr, v)
					case uint64:
						types.QualifyAttribute[uint64](attr, v)
					default:
						types.QualifyAttribute[string](attr, fmt.Sprintf("%v", v))
					}
				} else {
					types.QualifyAttribute[string](attr, "*")
				}
			}
			return types.NewUnknown(matchExprID, attr), nil
		}
	}
	return nil, nil
}

// attributeMatcher embeds the NamespacedAttribute interface which allows it to participate in
// AttributePattern matching against Attribute values without having to modify the code paths that
// identify Attributes in expressions.
type attributeMatcher struct {
	NamespacedAttribute
	qualifiers []Qualifier
	fac        *partialAttributeFactory
}

// AddQualifier implements the Attribute interface method.
func (m *attributeMatcher) AddQualifier(qual Qualifier) (Attribute, error) {
	// Add the qualifier to the embedded NamespacedAttribute. If the input to the Resolve
	// method is not a PartialActivation, or does not match an unknown attribute pattern, the
	// Resolve method is directly invoked on the underlying NamespacedAttribute.
	_, err := m.NamespacedAttribute.AddQualifier(qual)
	if err != nil {
		return nil, err
	}
	// The attributeMatcher overloads TryResolve and will attempt to match unknown patterns against
	// the variable name and qualifier set contained within the Attribute. These values are not
	// directly inspectable on the top-level NamespacedAttribute interface and so are tracked within
	// the attributeMatcher.
	m.qualifiers = append(m.qualifiers, qual)
	return m, nil
}

// Resolve is an implementation of the NamespacedAttribute interface method which tests
// for matching unknown attribute patterns and returns types.Unknown if present. Otherwise,
// the standard Resolve logic applies.
func (m *attributeMatcher) Resolve(vars Activation) (any, error) {
	id := m.NamespacedAttribute.ID()
	// Bug in how partial activation is resolved, should search parents as well.
	partial, isPartial := AsPartialActivation(vars)
	if isPartial {
		unk, err := m.fac.matchesUnknownPatterns(
			partial,
			id,
			m.CandidateVariableNames(),
			m.qualifiers)
		if err != nil {
			return nil, err
		}
		if unk != nil {
			return unk, nil
		}
	}
	return m.NamespacedAttribute.Resolve(vars)
}

// Qualify is an implementation of the Qualifier interface method.
func (m *attributeMatcher) Qualify(vars Activation, obj any) (any, error) {
	return attrQualify(m.fac, vars, obj, m)
}

// QualifyIfPresent is an implementation of the Qualifier interface method.
func (m *attributeMatcher) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) {
	return attrQualifyIfPresent(m.fac, vars, obj, m, presenceOnly)
}
