package main

import (
	"bytes"
	"fmt"
	"strings"
)

type EvalResult struct {
	vars  Vars
	rules []*Rule
}

type Evaluator struct {
	outVars  Vars
	outRules []*Rule
	vars     Vars
	lastRule *Rule

	filename string
	lineno   int
}

func newEvaluator(vars map[string]Var) *Evaluator {
	return &Evaluator{
		outVars: make(Vars),
		vars:    vars,
	}
}

func (ev *Evaluator) Value(v Value) []byte {
	var buf bytes.Buffer
	v.Eval(&buf, ev)
	return buf.Bytes()
}

// TODO(ukai): use unicode.IsSpace?
func isWhitespace(b byte) bool {
	switch b {
	case ' ', '\t', '\n', '\r':
		return true
	}
	return false
}

func (ev *Evaluator) Values(v Value) [][]byte {
	var buf bytes.Buffer
	v.Eval(&buf, ev)
	val := buf.Bytes()
	var values [][]byte
	b := -1
	for i := 0; i < len(val); i++ {
		if b < 0 {
			if isWhitespace(val[i]) {
				continue
			}
			b = i
		} else {
			if isWhitespace(val[i]) {
				values = append(values, val[b:i])
				b = -1
				continue
			}
		}
	}
	if b >= 0 {
		values = append(values, val[b:])
	}
	return values
}

// TODO(ukai): deprecated.
func (ev *Evaluator) evalExprBytes(ex string) []byte {
	v, _, err := parseExpr([]byte(ex), nil)
	if err != nil {
		panic(err)
	}
	return ev.Value(v)
}

func (ev *Evaluator) evalExpr(ex string) string {
	return string(ev.evalExprBytes(ex))
}

func (ev *Evaluator) evalAssign(ast *AssignAST) {
	ev.lastRule = nil
	lhs, rhs := ev.evalAssignAST(ast)
	Log("ASSIGN: %s=%q (flavor:%q)", lhs, rhs, rhs.Flavor())
	if len(lhs) == 0 {
		Error(ast.filename, ast.lineno, "*** empty variable name.")
	}
	ev.outVars.Assign(lhs, rhs)
}

func (ev *Evaluator) evalAssignAST(ast *AssignAST) (string, Var) {
	ev.filename = ast.filename
	ev.lineno = ast.lineno

	lhs := strings.TrimSpace(ev.evalExpr(ast.lhs))
	rhs := ast.evalRHS(ev, lhs)
	return lhs, rhs
}

func (ev *Evaluator) evalMaybeRule(ast *MaybeRuleAST) {
	ev.lastRule = nil
	ev.filename = ast.filename
	ev.lineno = ast.lineno

	expr := ast.expr
	if ast.semicolonIndex >= 0 {
		expr = expr[0:ast.semicolonIndex]
	}
	if ast.equalIndex >= 0 {
		expr = expr[0:ast.equalIndex]
	}
	line := ev.evalExpr(expr)
	if ast.equalIndex >= 0 {
		line += ast.expr[ast.equalIndex:]
	}
	Log("rule? %q=>%q", expr, line)

	// See semicolon.mk.
	if strings.TrimRight(line, " \t\n;") == "" {
		return
	}

	rule := &Rule{
		filename: ast.filename,
		lineno:   ast.lineno,
	}
	assign, err := rule.parse(line)
	if err != nil {
		Error(ast.filename, ast.lineno, "%v", err.Error())
	}
	Log("rule %q => outputs:%q, inputs:%q", line, rule.outputs, rule.inputs)

	// TODO: Pretty print.
	//Log("RULE: %s=%s (%d commands)", lhs, rhs, len(cmds))

	if assign != nil {
		if ast.semicolonIndex >= 0 {
			assign, err = rule.parse(ev.evalExpr(ast.expr))
			if err != nil {
				Error(ast.filename, ast.lineno, "%v", err.Error())
			}
		}
		rule.vars = make(Vars)
		lhs, rhs := ev.evalAssignAST(assign)
		Log("rule outputs:%q assign:%q=%q (flavor:%q)", rule.outputs, lhs, rhs, rhs.Flavor())
		rule.vars.Assign(lhs, rhs)
	} else {
		if ast.semicolonIndex > 0 {
			rule.cmds = append(rule.cmds, ast.expr[ast.semicolonIndex+1:])
		}
		Log("rule outputs:%q cmds:%q", rule.outputs, rule.cmds)
	}
	ev.lastRule = rule
	ev.outRules = append(ev.outRules, rule)
}

func (ev *Evaluator) evalCommand(ast *CommandAST) {
	ev.filename = ast.filename
	ev.lineno = ast.lineno
	if ev.lastRule == nil {
		// This could still be an assignment statement. See
		// assign_after_tab.mk.
		if strings.IndexByte(ast.cmd, '=') >= 0 {
			line := trimLeftSpace(ast.cmd)
			mk, err := ParseMakefileString(line, ast.filename, ast.lineno)
			if err != nil {
				panic(err)
			}
			if len(mk.stmts) == 1 && mk.stmts[0].(*AssignAST) != nil {
				ev.eval(mk.stmts[0])
			}
			return
		}
		Error(ast.filename, ast.lineno, "*** commands commence before first target.")
	}
	ev.lastRule.cmds = append(ev.lastRule.cmds, ast.cmd)
	if ev.lastRule.cmdLineno == 0 {
		ev.lastRule.cmdLineno = ast.lineno
	}
}

func (ev *Evaluator) LookupVar(name string) Var {
	v := ev.outVars.Lookup(name)
	if v.IsDefined() {
		return v
	}
	return ev.vars.Lookup(name)
}

func (ev *Evaluator) evalInclude(ast *IncludeAST) {
	ev.lastRule = nil
	ev.filename = ast.filename
	ev.lineno = ast.lineno

	// TODO: Handle glob
	v, _, err := parseExpr([]byte(ast.expr), nil)
	if err != nil {
		panic(err)
	}
	files := ev.Values(v)
	for _, f := range files {
		file := string(f)
		Log("Reading makefile `%s'", file)
		mk, err := ParseMakefile(file)
		if err != nil {
			if ast.op == "include" {
				panic(err)
			} else {
				continue
			}
		}

		makefileList := ev.outVars.Lookup("MAKEFILE_LIST")
		makefileList = makefileList.Append(ev, mk.filename)
		ev.outVars.Assign("MAKEFILE_LIST", makefileList)

		for _, stmt := range mk.stmts {
			ev.eval(stmt)
		}
	}
}

func (ev *Evaluator) evalIf(ast *IfAST) {
	var isTrue bool
	switch ast.op {
	case "ifdef", "ifndef":
		vname := ev.evalExpr(ast.lhs)
		v := ev.LookupVar(string(vname))
		value := ev.Value(v)
		isTrue = (len(value) > 0) == (ast.op == "ifdef")
		Log("%s lhs=%q value=%q => %t", ast.op, ast.lhs, value, isTrue)
	case "ifeq", "ifneq":
		lhs := ev.evalExpr(ast.lhs)
		rhs := ev.evalExpr(ast.rhs)
		isTrue = (lhs == rhs) == (ast.op == "ifeq")
		Log("%s lhs=%q %q rhs=%q %q => %t", ast.op, ast.lhs, lhs, ast.rhs, rhs, isTrue)
	default:
		panic(fmt.Sprintf("unknown if statement: %q", ast.op))
	}

	var stmts []AST
	if isTrue {
		stmts = ast.trueStmts
	} else {
		stmts = ast.falseStmts
	}
	for _, stmt := range stmts {
		ev.eval(stmt)
	}
}

func (ev *Evaluator) eval(ast AST) {
	ast.eval(ev)
}

func Eval(mk Makefile, vars Vars) (er *EvalResult, err error) {
	ev := newEvaluator(vars)
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("panic: %v", r)
		}
	}()

	makefile_list := vars.Lookup("MAKEFILE_LIST")
	makefile_list = makefile_list.Append(ev, mk.filename)
	ev.outVars.Assign("MAKEFILE_LIST", makefile_list)

	for _, stmt := range mk.stmts {
		ev.eval(stmt)
	}
	return &EvalResult{
		vars:  ev.outVars,
		rules: ev.outRules,
	}, nil
}
