// Copyright 2018 The 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 cue

import (
	"sort"

	"cuelang.org/go/cue/token"
	"golang.org/x/exp/errors"
	"golang.org/x/exp/errors/fmt"
)

type errCode int

const (
	codeNone errCode = iota
	codeFatal
	codeNotExist
	codeTypeError
	codeIncomplete
	codeCycle
)

func isIncomplete(v value) bool {
	if err, ok := v.(*bottom); ok {
		return err.code == codeIncomplete
	}
	return false
}

func recoverable(v value) bool {
	if err, ok := v.(*bottom); ok {
		switch err.code {
		case codeFatal,
			codeCycle: // only recoverable when explicitly handled and discarded
			return false
		}
	}
	return true
}

var errNotExists = &bottom{code: codeNotExist, msg: "undefined value"}

func exists(v value) bool {
	if err, ok := v.(*bottom); ok {
		return err.code != codeNotExist
	}
	return true
}

// bottom is the bottom of the value lattice. It is subsumed by all values.
type bottom struct {
	baseValue

	index          *index
	code           errCode
	value          value
	offendingValue value
	replacement    evaluated // for cycle resolution
	pos            source
	msg            string

	wrapped *bottom

	// TODO: file at which the error was generated in the code.
	// File positions of where the error occurred.
}

func (x *bottom) kind() kind { return bottomKind }

func (x *bottom) Position() []token.Position {
	if x.index != nil && x.index.fset != nil {
		return appendPositions(nil, x.index.fset, x.pos)
	}
	return nil
}

func appendPositions(pos []token.Position, fset *token.FileSet, src source) []token.Position {
	if src != nil {
		if p := src.Pos(); p != token.NoPos {
			if p >= sharedOffset {
				fset = sharedIndex.fset
			}
			return append(pos, fset.Position(src.Pos()))
		}
		if c := src.computed(); c != nil {
			pos = appendPositions(pos, fset, c.x)
			pos = appendPositions(pos, fset, c.y)
		}
	}
	return pos
}

func (x *bottom) Error() string { return fmt.Sprint(x) }

func (x *bottom) FormatError(p errors.Printer) error {
	p.Print(x.msg)
	if p.Detail() && x.index != nil && x.index.fset != nil {
		locs := appendLocations(nil, x.index.fset, x.pos)
		sort.Strings(locs)
		for _, l := range locs {
			p.Printf("%s\n", l)
		}
	}
	if x.wrapped != nil {
		return x.wrapped // nil interface
	}
	return nil
}

func appendLocations(locs []string, fset *token.FileSet, src source) []string {
	if src != nil {
		if p := src.Pos(); p != token.NoPos {
			if p >= sharedOffset {
				fset = sharedIndex.fset
			}
			return append(locs, fset.Position(src.Pos()).String())
		}
		if c := src.computed(); c != nil {
			locs = appendLocations(locs, fset, c.x)
			locs = appendLocations(locs, fset, c.y)
		}
	}
	return locs
}

func cycleError(v evaluated) *bottom {
	if err, ok := v.(*bottom); ok && err.code == codeCycle {
		return err
	}
	return nil
}

// sentinel values used for signalling a type of error.
var (
	// errNonGround =  // values are not compatible
	cycleSentinel = &bottom{
		code: codeCycle,
		msg:  "cycle detected",
	}

	// unifyNotSupported may be returned when a node implementation cannot
	// handle the other type. In this case it may still be the case that the
	// converse can be implemented.
	// unifyNotSupported node = &bottom{}
)

func (idx *index) mkErrUnify(src source, a, b evaluated) evaluated {
	if err := firstBottom(a, b); err != nil {
		return err
	}
	e := binSrc(src.Pos(), opUnify, a, b)
	// TODO: show string of values and show location of both values.
	return idx.mkErr(e, "incompatible values &(%s, %s)", a.kind(), b.kind())
}

func (c *context) mkIncompatible(src source, op op, a, b evaluated) evaluated {
	if err := firstBottom(a, b); err != nil {
		return err
	}
	e := mkBin(c, src.Pos(), op, a, b)
	return c.mkErr(e, "unsupported op %s(%s, %s)", op, a.kind(), b.kind())
}

func (idx *index) mkErr(src source, args ...interface{}) *bottom {
	e := &bottom{baseValue: src.base(), index: idx, pos: src}

	if v, ok := src.(value); ok {
		e.value = v
	}
	for i, a := range args {
		switch x := a.(type) {
		case errCode:
			e.code = x
		case *bottom:
			e.wrapped = x
			e.offendingValue = x
		case value:
			e.offendingValue = x
		case op:
			panic("no longer using offending value and op")
		case string:
			e.msg += fmt.Sprintf(x, args[i+1:]...)
			return e
		}
	}
	if e.code == codeNone && e.wrapped != nil {
		e.code = e.wrapped.code
	}
	return e
}

func isBottom(n value) bool {
	return n.kind() == bottomKind
}

func firstBottom(v ...value) evaluated {
	for _, b := range v {
		if isBottom(b) {
			return b.(*bottom)
		}
	}
	return nil
}

func expectType(idx *index, t kind, n evaluated) value {
	if isBottom(n) {
		return n
	}
	return idx.mkErr(n, "value should of type %s, found %s", n.kind(), t)
}

// TODO: consider returning a type or subsuption error for op != opUnify
