// Copyright 2020 CUE Authors
//
// 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 adt

// MatchAndInsert finds matching optional parts for a given Arc and adds its
// conjuncts. Bulk fields are only applied if no fields match, and additional
// constraints are only added if neither regular nor bulk fields match.
func (o *StructInfo) MatchAndInsert(c *OpContext, arc *Vertex) {
	env := o.Env

	closeInfo := o.CloseInfo
	closeInfo.IsClosed = false

	// Match normal fields
	matched := false
outer:
	for _, f := range o.Fields {
		if f.Label == arc.Label {
			for _, e := range f.Optional {
				arc.AddConjunct(MakeConjunct(env, e, closeInfo))
			}
			matched = true
			break outer
		}
	}

	if !arc.Label.IsRegular() {
		return
	}

	var label Value
	if o.types&HasComplexPattern != 0 && arc.Label.IsString() {
		label = arc.Label.ToValue(c)
	}

	if len(o.Bulk) > 0 {
		bulkEnv := *env
		bulkEnv.DynamicLabel = arc.Label
		bulkEnv.Deref = nil
		bulkEnv.Cycles = nil

		// match bulk optional fields / pattern properties
		for _, b := range o.Bulk {
			// if matched && f.additional {
			// 	continue
			// }
			if matchBulk(c, env, b, arc.Label, label) {
				matched = true
				info := closeInfo.SpawnSpan(b.Value, ConstraintSpan)
				arc.AddConjunct(MakeConjunct(&bulkEnv, b, info))
			}
		}
	}

	if matched || len(o.Additional) == 0 {
		return
	}

	addEnv := *env
	addEnv.Deref = nil
	addEnv.Cycles = nil

	// match others
	for _, x := range o.Additional {
		info := closeInfo
		if _, ok := x.(*Top); !ok {
			info = info.SpawnSpan(x, ConstraintSpan)
		}
		arc.AddConjunct(MakeConjunct(&addEnv, x, info))
	}
}

// matchBulk reports whether feature f matches the filter of x. It evaluation of
// the filter is erroneous, it returns false and the error will  be set in c.
func matchBulk(c *OpContext, env *Environment, x *BulkOptionalField, f Feature, label Value) bool {
	v := env.evalCached(c, x.Filter)

	// Fast-track certain cases.
	switch x := v.(type) {
	case *Bottom:
		if c.errs == nil {
			c.AddBottom(x)
		}
		return false
	case *Top:
		return true

	case *BasicType:
		return x.K&StringKind != 0

	case *BoundValue:
		switch x.Kind() {
		case StringKind:
			if label == nil {
				label = f.ToValue(c)
			}
			str := label.(*String).Str
			return x.validateStr(c, str)

		case IntKind:
			return x.validateInt(c, int64(f.Index()))
		}
	}

	n := Vertex{}
	m := MakeRootConjunct(env, v)
	n.AddConjunct(m)
	if label == nil {
		label = f.ToValue(c)
	}
	n.AddConjunct(MakeRootConjunct(m.Env, label))

	c.inConstraint++
	n.Finalize(c)
	c.inConstraint--

	b, _ := n.BaseValue.(*Bottom)
	return b == nil
}
