// 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 (
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/internal/core/adt"
)

func (v Value) toErr(b *bottom) (err errors.Error) {
	errs := errors.Errors(b.Err)
	if len(errs) > 1 {
		for _, e := range errs {
			bb := *b
			bb.Err = e
			err = errors.Append(err, &valueError{v: v, err: &bb})
		}
		return 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) Bottom() *adt.Bottom { return e.err }

func (e *valueError) Error() string {
	return errors.String(e)
}

func (e *valueError) Position() token.Pos {
	if e.err.Err != nil {
		return e.err.Err.Position()
	}
	src := e.err.Source()
	if src == nil {
		return token.NoPos
	}
	return src.Pos()
}

func (e *valueError) InputPositions() []token.Pos {
	if e.err.Err == nil {
		return nil
	}
	return e.err.Err.InputPositions()
}

func (e *valueError) Msg() (string, []interface{}) {
	if e.err.Err == nil {
		return "", nil
	}
	return e.err.Err.Msg()
}

func (e *valueError) Path() (a []string) {
	if e.err.Err != nil {
		a = e.err.Err.Path()
		if a != nil {
			return a
		}
	}
	return e.v.appendPath(nil)
}

type errCode = adt.ErrorCode

const (
	codeNotExist   = adt.NotExistError
	codeIncomplete = adt.IncompleteError
)

var errNotExists = &adt.Bottom{
	Code: codeNotExist,
	Err:  errors.Newf(token.NoPos, "undefined value"),
}

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

func (idx *index) mkErr(src source, args ...interface{}) *bottom {
	var e *adt.Bottom
	var code errCode = -1
outer:
	for i, a := range args {
		switch x := a.(type) {
		case errCode:
			code = x
		case *bottom:
			e = adt.CombineErrors(nil, e, x)
		case []*bottom:
			for _, b := range x {
				e = adt.CombineErrors(nil, e, b)
			}
		case errors.Error:
			e = adt.CombineErrors(nil, e, &adt.Bottom{Err: x})
		case value:
		case string:
			args := args[i+1:]
			// Do not expand message so that errors can be localized.
			pos := pos(src)
			if code < 0 {
				code = 0
			}
			e = adt.CombineErrors(nil, e, &adt.Bottom{
				Code: code,
				Err:  errors.Newf(pos, x, args...),
			})
			break outer
		}
	}
	if code >= 0 {
		e.Code = code
	}
	return e
}
