// 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"
	"reflect"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
)

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) InputPositions() []token.Pos { return nil }

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

func (v Value) toErr(b *bottom) errors.Error {
	if b.err != nil {
		return b.err
	}
	return &valueError{
		v:   v,
		err: b,
	}
}

var _ errors.Error = &valueError{}

// A valueError is returned as a result of evaluating a value.
type valueError struct {
	v   Value
	err *bottom
}

func (e *valueError) Error() string {
	return fmt.Sprint(e.err)
}

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

func (e *valueError) InputPositions() []token.Pos {
	return e.err.Positions()
}

func (e *valueError) Msg() (string, []interface{}) {
	return e.err.Msg()
}

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

type errCode int

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

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

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

var errNotExists = &bottom{code: codeNotExist, format: "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
	pos       source
	format    string
	args      []interface{}

	err     errors.Error // pass-through from higher-level API
	value   value
	wrapped *bottom
}

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

func (x *bottom) Positions() []token.Pos {
	if x.index != nil { // TODO: remove check?
		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 _, isUnify := b.op.unifyType(); isUnify {
				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) Msg() (format string, args []interface{}) {
	ctx := x.index.newContext()
	// We need to copy to avoid races.
	args = make([]interface{}, len(x.args))
	copy(args, x.args)
	preEvalArgs(ctx, args)
	return x.format, x.args
}

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

func (x *bottom) Format(s fmt.State, verb rune) {
	msg, args := x.Msg()
	fmt.Fprintf(s, msg, args...)
}

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

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, "invalid operation %s %s %s (mismatched types %s and %s)",
		c.str(a), op, c.str(b), 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
	}
outer:
	for i, a := range args {
		switch x := a.(type) {
		case errCode:
			e.code = x
		case *bottom:
			e.wrapped = x
		case errors.Error:
			e.err = x
		case value:
		case string:
			e.format = x
			e.args = args[i+1:]
			// Do not expand message so that errors can be localized.
			for i, a := range e.args {
				e.args[i] = fixArg(idx, a)
			}
			break outer
		}
	}
	if e.code == codeNone && e.wrapped != nil {
		e.code = e.wrapped.code
	}
	return e
}

func fixArg(idx *index, x interface{}) interface{} {
	switch x.(type) {
	case uint, int, string:
		return x
	case value:
		return x
	}
	t := reflect.TypeOf(x)
	// Store all non-ptr types as is, as they cannot change.
	if k := t.Kind(); k == reflect.String || k <= reflect.Complex128 {
		return x
	}
	return fmt.Sprint(x)
}

// preEvalArgs is used to expand value arguments just before printing.
func preEvalArgs(ctx *context, args []interface{}) {
	for i, a := range args {
		switch v := a.(type) {
		case *bottom:
			args[i] = v.msg()
		case value:
			// TODO: convert to Go values so that localization frameworks
			// can format values accordingly.
			args[i] = ctx.str(v)
		}
	}
}

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

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