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

import (
	"bytes"

	"cuelang.org/go/cue/errors"
	"cuelang.org/go/internal/core/adt"
)

func (s *subsumer) values(a, b adt.Value) (result bool) {
	defer func() {
		if !result && s.gt == nil && s.lt == nil {
			s.gt = a
			s.lt = b
		}
	}()

	if a == b {
		return true
	}

	if s.Defaults {
		b = adt.Default(b)
	}

	switch b := b.(type) {
	case *adt.Bottom:
		// If the value is incomplete, the error is not final. So either check
		// structural equivalence or return an error.
		return !b.IsIncomplete()

	case *adt.Vertex:
		if a, ok := a.(*adt.Vertex); ok {
			return s.vertices(a, b)
		}
		if v, ok := b.BaseValue.(adt.Value); ok {
			// Safe to ignore arcs of w.
			return s.values(a, v)
		}
		// Check based on first value.

	case *adt.Conjunction:
		if _, ok := a.(*adt.Conjunction); ok {
			break
		}
		for _, y := range b.Values {
			if s.values(a, y) {
				return true
			}
		}
		return false

	case *adt.Disjunction:
		if _, ok := a.(*adt.Disjunction); ok {
			break
		}

		for _, y := range b.Values {
			if !s.values(a, y) {
				return false
			}
		}
		return true

	case *adt.NodeLink:
		// Do not descend into NodeLinks to avoid processing cycles.
		// TODO: this would work better if all equal nodes shared the same
		// node link.
		return deref(a) == deref(b)
	}

	switch x := a.(type) {
	case *adt.Top:
		return true

	case *adt.Bottom:
		// isBottom(b) was already tested above.
		return false

	case *adt.BasicType:
		k := b.Kind()
		return x.K&k == k

	case *adt.BoundValue:
		return s.bound(x, b)

	case *adt.Builtin:
		return x == b

	case *adt.BuiltinValidator:
		if y := s.ctx.Validate(x, b); y != nil {
			s.errs = errors.Append(s.errs, y.Err)
			return false
		}
		return true

	case *adt.Null:
		return b.Kind() == adt.NullKind

	case *adt.Bool:
		y, ok := b.(*adt.Bool)
		return ok && x.B == y.B

	case *adt.Num:
		y, ok := b.(*adt.Num)
		return ok && x.K&y.K == y.K && test(s.ctx, x, adt.EqualOp, x, y)

	case *adt.String:
		y, ok := b.(*adt.String)
		return ok && x.Str == y.Str

	case *adt.Bytes:
		y, ok := b.(*adt.Bytes)
		return ok && bytes.Equal(x.B, y.B)

	case *adt.Vertex:
		y, ok := b.(*adt.Vertex)
		if ok {
			return s.vertices(x, y)
		}

		// TODO: Under what conditions can we cast to the value?
		if v, _ := x.BaseValue.(adt.Value); v != nil {
			return s.values(v, b)
		}
		return false

	case *adt.Conjunction:
		if y, ok := b.(*adt.Conjunction); ok {
			// A Conjunction subsumes another Conjunction if for all values a in
			// x there is a value b in y such that a subsumes b.
			//
			// This assumes overlapping ranges in disjunctions are merged.If
			// this is not the case, subsumes will return a false negative,
			// which is allowed.
		outerC:
			for _, a := range x.Values {
				for _, b := range y.Values {
					if s.values(a, b) {
						continue outerC
					}
				}
				// TODO: should this be marked as inexact?
				return false
			}
			return true
		}
		subsumed := true
		for _, a := range x.Values {
			subsumed = subsumed && s.values(a, b)
		}
		return subsumed

	case *adt.Disjunction:
		// A Disjunction subsumes another Disjunction if all values of y are
		// subsumed by any of the values of x, and default values in y are
		// subsumed by the default values of x.
		//
		// This assumes that overlapping ranges in x are merged. If this is not
		// the case, subsumes will return a false negative, which is allowed.
		if y, ok := b.(*adt.Disjunction); ok {
			// at least one value in x should subsume each value in d.
		outerD:
			for i, b := range y.Values {
				bDefault := i < y.NumDefaults
				// v is subsumed if any value in x subsumes v.
				for j, a := range x.Values {
					aDefault := j < x.NumDefaults
					if (aDefault || !bDefault) && s.values(a, b) {
						continue outerD
					}
				}
				return false
			}
			return true
		}
		// b is subsumed if any value in x subsumes b.
		for _, a := range x.Values {
			if s.values(a, b) {
				return true
			}
		}
		// TODO: should this be marked as inexact?
		return false

	case *adt.NodeLink:
		return deref(x) == deref(b)
	}
	return false
}

func deref(v adt.Expr) *adt.Vertex {
	switch x := v.(type) {
	case *adt.Vertex:
		return x
	case *adt.NodeLink:
		return x.Node
	}
	return nil
}

func (s *subsumer) bound(x *adt.BoundValue, v adt.Value) bool {
	ctx := s.ctx
	if isBottom(v) {
		return true
	}

	switch y := v.(type) {
	case *adt.BoundValue:
		if !adt.IsConcrete(y.Value) {
			return false
		}

		kx := x.Kind()
		ky := y.Kind()
		if (kx&ky)&^kx != 0 {
			return false
		}
		// x subsumes y if
		// x: >= a, y: >= b ==> a <= b
		// x: >= a, y: >  b ==> a <= b
		// x: >  a, y: >  b ==> a <= b
		// x: >  a, y: >= b ==> a < b
		//
		// x: <= a, y: <= b ==> a >= b
		//
		// x: != a, y: != b ==> a != b
		//
		// false if types or op direction doesn't match

		xv := x.Value
		yv := y.Value
		switch x.Op {
		case adt.GreaterThanOp:
			if y.Op == adt.GreaterEqualOp {
				return test(ctx, x, adt.LessThanOp, xv, yv)
			}
			fallthrough
		case adt.GreaterEqualOp:
			if y.Op == adt.GreaterThanOp || y.Op == adt.GreaterEqualOp {
				return test(ctx, x, adt.LessEqualOp, xv, yv)
			}
		case adt.LessThanOp:
			if y.Op == adt.LessEqualOp {
				return test(ctx, x, adt.GreaterThanOp, xv, yv)
			}
			fallthrough
		case adt.LessEqualOp:
			if y.Op == adt.LessThanOp || y.Op == adt.LessEqualOp {
				return test(ctx, x, adt.GreaterEqualOp, xv, yv)
			}
		case adt.NotEqualOp:
			switch y.Op {
			case adt.NotEqualOp:
				return test(ctx, x, adt.EqualOp, xv, yv)
			case adt.GreaterEqualOp:
				return test(ctx, x, adt.LessThanOp, xv, yv)
			case adt.GreaterThanOp:
				return test(ctx, x, adt.LessEqualOp, xv, yv)
			case adt.LessThanOp:
				return test(ctx, x, adt.GreaterEqualOp, xv, yv)
			case adt.LessEqualOp:
				return test(ctx, x, adt.GreaterThanOp, xv, yv)
			}

		case adt.MatchOp, adt.NotMatchOp:
			// these are just approximations
			if y.Op == x.Op {
				return test(ctx, x, adt.EqualOp, xv, yv)
			}

		default:
			// adt.NotEqualOp already handled above.
			panic("cue: undefined bound mode")
		}

	case *adt.Num, *adt.String, *adt.Bool:
		return test(ctx, x, x.Op, y, x.Value)
	}
	return false
}

func test(ctx *adt.OpContext, src adt.Node, op adt.Op, gt, lt adt.Value) bool {
	x := adt.BinOp(ctx, op, gt, lt)
	b, ok := x.(*adt.Bool)
	return ok && b.B
}
