package calc

import (
	"fmt"

	"go.skia.org/infra/go/vec32"
	"go.skia.org/infra/perf/go/types"
)

const (
	NodeError NodeType = iota
	NodeFunc
	NodeNum
	NodeString
)

type (
	NodeType         int
	RowsFromQuery    func(q string) (types.TraceSet, error)
	RowsFromShortcut func(id string) (types.TraceSet, error)
)

func newRow(rows types.TraceSet) types.Trace {
	if len(rows) == 0 {
		return []float32{}
	}
	var n int
	for _, v := range rows {
		n = len(v)
		break
	}
	ret := make([]float32, n, n)
	for i := range ret {
		ret[i] = vec32.MissingDataSentinel
	}
	return ret
}

// Node is a single node in the parse tree.
type Node struct {
	Typ  NodeType
	Val  string
	Args []*Node
}

// newNode creates a new Node of the given type and value.
func newNode(val string, typ NodeType) *Node {
	return &Node{
		Typ:  typ,
		Val:  val,
		Args: []*Node{},
	}
}

// Evaluates a node. Only valid to call on Nodes of type NodeFunc.
func (n *Node) Eval(ctx *Context) (types.TraceSet, error) {
	if n.Typ != NodeFunc {
		return nil, fmt.Errorf("Tried to call eval on a non-Func node: %s", n.Val)
	}
	if f, ok := ctx.Funcs[n.Val]; ok {
		return f.Eval(ctx, n)
	} else {
		return nil, fmt.Errorf("Unknown function name: %s", n.Val)
	}
}

// Func defines a type for functions that can be used in the parser.
//
// The traces returned will always have a Param of "id" that identifies
// the trace. See DESIGN.md for the Trace ID naming conventions.
type Func interface {
	Eval(*Context, *Node) (types.TraceSet, error)
	Describe() string
}

// Context stores all the info for a single parser.
//
// A Context is not safe to call from multiple go routines.
type Context struct {
	RowsFromQuery    RowsFromQuery
	RowsFromShortcut RowsFromShortcut
	Funcs            map[string]Func
	formula          string // The current formula being evaluated.
}

// NewContext create a new parsing context that includes the basic functions.
func NewContext(rowsFromQuery RowsFromQuery, rowsFromShortcut RowsFromShortcut) *Context {
	return &Context{
		RowsFromQuery:    rowsFromQuery,
		RowsFromShortcut: rowsFromShortcut,
		Funcs: map[string]Func{
			"filter":       filterFunc,
			"shortcut":     shortcutFunc,
			"norm":         normFunc,
			"fill":         fillFunc,
			"ave":          aveFunc,
			"avg":          aveFunc,
			"count":        countFunc,
			"ratio":        ratioFunc,
			"sum":          sumFunc,
			"geo":          geoFunc,
			"log":          logFunc,
			"trace_ave":    traceAveFunc,
			"trace_avg":    traceAveFunc,
			"trace_stddev": traceStdDevFunc,
			"trace_cov":    traceCovFunc,
			"step":         traceStepFunc,
			"scale_by_ave": scaleByAveFunc,
			"scale_by_avg": scaleByAveFunc,
			"iqrr":         iqrrFunc,
		},
	}
}

// Eval parses and evaluates the given string expression and returns the Traces, or
// an error.
func (ctx *Context) Eval(exp string) (types.TraceSet, error) {
	ctx.formula = exp
	n, err := parse(exp)
	if err != nil {
		return nil, fmt.Errorf("Eval: failed to parse the expression: %s", err)
	}
	return n.Eval(ctx)
}

// parse starts the parsing.
func parse(input string) (*Node, error) {
	l := newLexer(input)
	return parseExp(l)
}

// parseExp parses an expression.
//
// Something of the form:
//
//    fn(arg1, args2)
//
func parseExp(l *lexer) (*Node, error) {
	it := l.nextItem()
	if it.typ != itemIdentifier {
		return nil, fmt.Errorf("Expression: must begin with an identifier")
	}
	n := newNode(it.val, NodeFunc)
	it = l.nextItem()
	if it.typ != itemLParen {
		return nil, fmt.Errorf("Expression: didn't find '(' after an identifier.")
	}
	if err := parseArgs(l, n); err != nil {
		return nil, fmt.Errorf("Expression: failed parsing arguments: %s", err)
	}
	it = l.nextItem()
	if it.typ != itemRParen {
		return nil, fmt.Errorf("Expression: didn't find ')' after arguments.")
	}
	return n, nil
}

// parseArgs parses the arguments to a function.
//
// Something of the form:
//
//    arg1, arg2, arg3
//
// It terminates when it sees a closing paren, or an invalid token.
func parseArgs(l *lexer, p *Node) error {
Loop:
	for {
		it := l.peekItem()
		switch it.typ {
		case itemIdentifier:
			next, err := parseExp(l)
			if err != nil {
				return fmt.Errorf("Failed parsing args: %s", err)
			}
			p.Args = append(p.Args, next)
		case itemString:
			l.nextItem()
			node := newNode(it.val, NodeString)
			p.Args = append(p.Args, node)
		case itemNum:
			l.nextItem()
			node := newNode(it.val, NodeNum)
			p.Args = append(p.Args, node)
		case itemComma:
			l.nextItem()
			continue
		case itemRParen:
			break Loop
		default:
			return fmt.Errorf("Invalid token in args: %d", it.typ)
		}
	}
	return nil
}
