// Copyright 2019 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 task provides a registry for tasks to be used by commands.
package task

import (
	"context"
	"io"
	"sync"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/internal"
	"cuelang.org/go/internal/core/adt"
)

// A Context provides context for running a task.
type Context struct {
	Context context.Context
	Stdin   io.Reader
	Stdout  io.Writer
	Stderr  io.Writer
	Obj     cue.Value
	Err     errors.Error
}

func (c *Context) Lookup(field string) cue.Value {
	f := c.Obj.Lookup(field)
	if !f.Exists() {
		c.addErr(f, nil, "could not find field %q", field)
		return cue.Value{}
	}
	if err := f.Err(); err != nil {
		c.Err = errors.Append(c.Err, errors.Promote(err, "lookup"))
	}
	return f
}

func (c *Context) Int64(field string) int64 {
	f := c.Obj.Lookup(field)
	value, err := f.Int64()
	if err != nil {
		// TODO: use v for position for now, as f has not yet a
		// position associated with it.
		c.addErr(f, err, "invalid integer argument")
		return 0
	}
	return value
}

func (c *Context) String(field string) string {
	f := c.Obj.Lookup(field)
	value, err := f.String()
	if err != nil {
		// TODO: use v for position for now, as f has not yet a
		// position associated with it.
		c.addErr(f, err, "invalid string argument")
		return ""
	}
	return value
}

func (c *Context) Bytes(field string) []byte {
	f := c.Obj.Lookup(field)
	value, err := f.Bytes()
	if err != nil {
		c.addErr(f, err, "invalid bytes argument")
		return nil
	}
	return value
}

func (c *Context) addErr(v cue.Value, wrap error, format string, args ...interface{}) {

	err := &taskError{
		task:    c.Obj,
		v:       v,
		Message: errors.NewMessage(format, args),
		err:     wrap,
	}
	c.Err = errors.Append(c.Err, err)
}

// taskError wraps some error values to retain position information about the
// error.
type taskError struct {
	task cue.Value
	v    cue.Value
	errors.Message
	err error
}

var _ errors.Error = &taskError{}

func (t *taskError) Path() (a []string) {
	for _, x := range t.v.Path().Selectors() {
		a = append(a, x.String())
	}
	return a
}

func (t *taskError) Position() token.Pos {
	return t.task.Pos()
}

func (t *taskError) InputPositions() (a []token.Pos) {
	_, nx := internal.CoreValue(t.v)

	for _, x := range nx.(*adt.Vertex).Conjuncts {
		if src := x.Source(); src != nil {
			a = append(a, src.Pos())
		}
	}
	return a
}

func (t *taskError) Unwrap() error { return t.err }

// A RunnerFunc creates a Runner.
type RunnerFunc func(v cue.Value) (Runner, error)

// A Runner defines a command type.
type Runner interface {
	// Init is called with the original configuration before any task is run.
	// As a result, the configuration may be incomplete, but allows some
	// validation before tasks are kicked off.
	// Init(v cue.Value)

	// Runner runs given the current value and returns a new value which is to
	// be unified with the original result.
	Run(ctx *Context) (results interface{}, err error)
}

// Register registers a task for cue commands.
func Register(key string, f RunnerFunc) {
	runners.Store(key, f)
}

// Lookup returns the RunnerFunc for a key.
func Lookup(key string) RunnerFunc {
	v, ok := runners.Load(key)
	if !ok {
		return nil
	}
	return v.(RunnerFunc)
}

var runners sync.Map
