// 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 (
	"fmt"
	"sort"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
	"golang.org/x/xerrors"
)

var _ errors.Error = &nodeError{}

// A nodeError is an error associated with processing an AST node.
type nodeError struct {
	path []string // optional
	n    ast.Node

	errors.Message
}

func nodeErrorf(n ast.Node, format string, args ...interface{}) *nodeError {
	return &nodeError{
		n:       n,
		Message: errors.NewMessage(format, args),
	}
}

func (e *nodeError) Position() token.Pos {
	return e.n.Pos()
}

func (e *nodeError) Path() []string {
	return e.path
}

func (v Value) toErr(b *bottom) errors.Error {
	return &valueError{
		Message: errors.NewMessage(b.msg, nil),
		v:       v,
		err:     b,
	}
}

var _ errors.Error = &valueError{}

// A valueError is returned as a result of evaluating a value.
type valueError struct {
	errors.Message

	v   Value
	err *bottom
}

func (e *valueError) Position() token.Pos {
	return e.err.pos.Pos()
}

func (e *valueError) Path() (a []string) {
	a, _ = e.v.path.appendPath(a, e.v.idx)
	return a
}

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
	exprDepth      int
	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) Positions() []token.Pos {
	if x.index != nil {
		return appendPositions(nil, x.pos)
	}
	return nil
}

func appendPositions(pos []token.Pos, src source) []token.Pos {
	if src != nil {
		if b, ok := src.(*binaryExpr); ok {
			if b.op == opUnify {
				pos = appendPositions(pos, b.left)
				pos = appendPositions(pos, b.right)
			}
		}
		if p := src.Pos(); p != token.NoPos {
			return append(pos, src.Pos())
		}
		if c := src.computed(); c != nil {
			pos = appendPositions(pos, c.x)
			pos = appendPositions(pos, c.y)
		}
	}
	return pos
}

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

func (x *bottom) Format(s fmt.State, verb rune) {
	xerrors.FormatError(x, s, verb)
}

func (x *bottom) FormatError(p xerrors.Printer) error {
	p.Print(x.msg)
	if p.Detail() && x.index != nil {
		locs := appendLocations(nil, 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, src source) []string {
	if src != nil {
		if p := src.Pos(); p != token.NoPos {
			return append(locs, src.Pos().String())
		}
		if c := src.computed(); c != nil {
			locs = appendLocations(locs, c.x)
			locs = appendLocations(locs, c.y)
		}
	}
	return locs
}

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

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
