// 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 {
		a = adt.Default(a)
		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)
		}
		// Safe to ignore arcs of w.
		return s.values(a, b.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 {
			// 	// Under what conditions can we cast to the value?
			if len(x.Arcs) == 0 && x.Value != nil {
				return s.values(x.Value, b)
			}
			return false
		}
		return s.vertices(x, y)

	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
}
