// 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 eval

// TODO: rename this file to fieldset.go

import (
	"cuelang.org/go/internal/core/adt"
)

// fieldSet represents the fields for a single struct literal, along
// the constraints of fields that may be added.
type fieldSet struct {
	next *fieldSet
	pos  adt.Node

	// TODO: look at consecutive identical environments to figure out
	// what belongs to same definition?
	env *adt.Environment
	id  adt.ID

	// field marks the optional conjuncts of all explicit fields.
	// Required fields are marked as empty
	fields []field

	// literal map[adt.Feature][]adt.Node

	// excluded are all literal fields that already exist.
	bulk       []bulkField
	additional []adt.Expr
	isOpen     bool // has a ...
}

func (o *fieldSet) OptionalTypes() (mask adt.OptionalType) {
	for _, f := range o.fields {
		if len(f.optional) > 0 {
			mask = adt.HasField
			break
		}
	}
	for _, b := range o.bulk {
		if b.expr == nil {
			mask |= adt.HasDynamic
		} else {
			mask |= adt.HasPattern
		}
	}
	if o.additional != nil {
		mask |= adt.HasAdditional
	}
	if o.isOpen {
		mask |= adt.IsOpen
	}
	return mask
}

type field struct {
	label    adt.Feature
	optional []adt.Node
}

type bulkField struct {
	check fieldMatcher
	expr  adt.Node // *adt.BulkOptionalField // Conjunct
}

func (o *fieldSet) Accept(c *adt.OpContext, f adt.Feature) bool {
	if len(o.additional) > 0 {
		return true
	}
	if o.fieldIndex(f) >= 0 {
		return true
	}
	for _, b := range o.bulk {
		if b.check.Match(c, f) {
			return true
		}
	}
	return false
}

// 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 *fieldSet) MatchAndInsert(c *adt.OpContext, arc *adt.Vertex) {
	env := o.env

	// Match normal fields
	p := 0
	for ; p < len(o.fields); p++ {
		if o.fields[p].label == arc.Label {
			break
		}
	}
	if p < len(o.fields) {
		for _, e := range o.fields[p].optional {
			arc.AddConjunct(adt.MakeConjunct(env, e, o.id))
		}
		return
	}

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

	bulkEnv := *env
	bulkEnv.DynamicLabel = arc.Label
	bulkEnv.Deref = nil
	bulkEnv.Cycles = nil

	// match bulk optional fields / pattern properties
	matched := false
	for _, f := range o.bulk {
		if f.check.Match(c, arc.Label) {
			matched = true
			if f.expr != nil {
				arc.AddConjunct(adt.MakeConjunct(&bulkEnv, f.expr, o.id))
			}
		}
	}
	if matched {
		return
	}

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

	// match others
	for _, x := range o.additional {
		arc.AddConjunct(adt.MakeConjunct(&addEnv, x, o.id))
	}
}

func (o *fieldSet) fieldIndex(f adt.Feature) int {
	for i := range o.fields {
		if o.fields[i].label == f {
			return i
		}
	}
	return -1
}

func (o *fieldSet) MarkField(c *adt.OpContext, f adt.Feature) {
	if o.fieldIndex(f) < 0 {
		o.fields = append(o.fields, field{label: f})
	}
}

func (o *fieldSet) AddOptional(c *adt.OpContext, x *adt.OptionalField) {
	p := o.fieldIndex(x.Label)
	if p < 0 {
		p = len(o.fields)
		o.fields = append(o.fields, field{label: x.Label})
	}
	o.fields[p].optional = append(o.fields[p].optional, x)
}

func (o *fieldSet) AddDynamic(c *adt.OpContext, env *adt.Environment, x *adt.DynamicField) {
	// not in bulk: count as regular field?
	o.bulk = append(o.bulk, bulkField{dynamicMatcher{env, x.Key}, nil})
}

func (o *fieldSet) AddBulk(c *adt.OpContext, x *adt.BulkOptionalField) {
	v, ok := c.Evaluate(o.env, x.Filter)
	if !ok {
		// TODO: handle dynamically
		return
	}

	if m := o.getMatcher(c, v); m != nil {
		o.bulk = append(o.bulk, bulkField{m, x})
	}
}

func (o *fieldSet) getMatcher(c *adt.OpContext, v adt.Value) fieldMatcher {
	switch f := v.(type) {
	case *adt.Top:
		return typeMatcher(adt.TopKind)

	case *adt.BasicType:
		return typeMatcher(f.K)

	default:
		return o.newPatternMatcher(c, v)
	}
}

func (o *fieldSet) AddEllipsis(c *adt.OpContext, x *adt.Ellipsis) {
	expr := x.Value
	if x.Value == nil {
		o.isOpen = true
		expr = &adt.Top{}
	}
	o.additional = append(o.additional, expr)
}

type fieldMatcher interface {
	Match(c *adt.OpContext, f adt.Feature) bool
}

type typeMatcher adt.Kind

func (m typeMatcher) Match(c *adt.OpContext, f adt.Feature) bool {
	switch f.Typ() {
	case adt.StringLabel:
		return adt.Kind(m)&adt.StringKind != 0

	case adt.IntLabel:
		return adt.Kind(m)&adt.IntKind != 0
	}
	return false
}

type dynamicMatcher struct {
	env  *adt.Environment
	expr adt.Expr
}

func (m dynamicMatcher) Match(c *adt.OpContext, f adt.Feature) bool {
	if !f.IsRegular() || !f.IsString() {
		return false
	}
	v, ok := c.Evaluate(m.env, m.expr)
	if !ok {
		return false
	}
	s, ok := v.(*adt.String)
	if !ok {
		return false
	}
	label := f.StringValue(c)
	return label == s.Str
}

type patternMatcher adt.Conjunct

func (m patternMatcher) Match(c *adt.OpContext, f adt.Feature) bool {
	v := adt.Vertex{}
	v.AddConjunct(adt.Conjunct(m))
	label := f.ToValue(c)
	v.AddConjunct(adt.MakeRootConjunct(m.Env, label))
	v.Finalize(c)
	b, _ := v.Value.(*adt.Bottom)
	return b == nil
}

func (o *fieldSet) newPatternMatcher(ctx *adt.OpContext, x adt.Value) fieldMatcher {
	c := adt.MakeRootConjunct(o.env, x)
	return patternMatcher(c)
}
