package toml

import (
	"fmt"
)

// support function to set positions for tomlValues
// NOTE: this is done to allow ctx.lastPosition to indicate the start of any
// values returned by the query engines
func tomlValueCheck(node interface{}, ctx *queryContext) interface{} {
	switch castNode := node.(type) {
	case *tomlValue:
		ctx.lastPosition = castNode.position
		return castNode.value
	case []*TomlTree:
		if len(castNode) > 0 {
			ctx.lastPosition = castNode[0].position
		}
		return node
	default:
		return node
	}
}

// base match
type matchBase struct {
	next pathFn
}

func (f *matchBase) setNext(next pathFn) {
	f.next = next
}

// terminating functor - gathers results
type terminatingFn struct {
	// empty
}

func newTerminatingFn() *terminatingFn {
	return &terminatingFn{}
}

func (f *terminatingFn) setNext(next pathFn) {
	// do nothing
}

func (f *terminatingFn) call(node interface{}, ctx *queryContext) {
	switch castNode := node.(type) {
	case *TomlTree:
		ctx.result.appendResult(node, castNode.position)
	case *tomlValue:
		ctx.result.appendResult(node, castNode.position)
	default:
		// use last position for scalars
		ctx.result.appendResult(node, ctx.lastPosition)
	}
}

// match single key
type matchKeyFn struct {
	matchBase
	Name string
}

func newMatchKeyFn(name string) *matchKeyFn {
	return &matchKeyFn{Name: name}
}

func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
	if tree, ok := node.(*TomlTree); ok {
		item := tree.values[f.Name]
		if item != nil {
			f.next.call(item, ctx)
		}
	}
}

// match single index
type matchIndexFn struct {
	matchBase
	Idx int
}

func newMatchIndexFn(idx int) *matchIndexFn {
	return &matchIndexFn{Idx: idx}
}

func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
	if arr, ok := tomlValueCheck(node, ctx).([]interface{}); ok {
		if f.Idx < len(arr) && f.Idx >= 0 {
			f.next.call(arr[f.Idx], ctx)
		}
	}
}

// filter by slicing
type matchSliceFn struct {
	matchBase
	Start, End, Step int
}

func newMatchSliceFn(start, end, step int) *matchSliceFn {
	return &matchSliceFn{Start: start, End: end, Step: step}
}

func (f *matchSliceFn) call(node interface{}, ctx *queryContext) {
	if arr, ok := tomlValueCheck(node, ctx).([]interface{}); ok {
		// adjust indexes for negative values, reverse ordering
		realStart, realEnd := f.Start, f.End
		if realStart < 0 {
			realStart = len(arr) + realStart
		}
		if realEnd < 0 {
			realEnd = len(arr) + realEnd
		}
		if realEnd < realStart {
			realEnd, realStart = realStart, realEnd // swap
		}
		// loop and gather
		for idx := realStart; idx < realEnd; idx += f.Step {
			f.next.call(arr[idx], ctx)
		}
	}
}

// match anything
type matchAnyFn struct {
	matchBase
}

func newMatchAnyFn() *matchAnyFn {
	return &matchAnyFn{}
}

func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
	if tree, ok := node.(*TomlTree); ok {
		for _, v := range tree.values {
			f.next.call(v, ctx)
		}
	}
}

// filter through union
type matchUnionFn struct {
	Union []pathFn
}

func (f *matchUnionFn) setNext(next pathFn) {
	for _, fn := range f.Union {
		fn.setNext(next)
	}
}

func (f *matchUnionFn) call(node interface{}, ctx *queryContext) {
	for _, fn := range f.Union {
		fn.call(node, ctx)
	}
}

// match every single last node in the tree
type matchRecursiveFn struct {
	matchBase
}

func newMatchRecursiveFn() *matchRecursiveFn {
	return &matchRecursiveFn{}
}

func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
	if tree, ok := node.(*TomlTree); ok {
		var visit func(tree *TomlTree)
		visit = func(tree *TomlTree) {
			for _, v := range tree.values {
				f.next.call(v, ctx)
				switch node := v.(type) {
				case *TomlTree:
					visit(node)
				case []*TomlTree:
					for _, subtree := range node {
						visit(subtree)
					}
				}
			}
		}
		f.next.call(tree, ctx)
		visit(tree)
	}
}

// match based on an externally provided functional filter
type matchFilterFn struct {
	matchBase
	Pos  Position
	Name string
}

func newMatchFilterFn(name string, pos Position) *matchFilterFn {
	return &matchFilterFn{Name: name, Pos: pos}
}

func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
	fn, ok := (*ctx.filters)[f.Name]
	if !ok {
		panic(fmt.Sprintf("%s: query context does not have filter '%s'",
			f.Pos.String(), f.Name))
	}
	switch castNode := tomlValueCheck(node, ctx).(type) {
	case *TomlTree:
		for _, v := range castNode.values {
			if tv, ok := v.(*tomlValue); ok {
				if fn(tv.value) {
					f.next.call(v, ctx)
				}
			} else {
				if fn(v) {
					f.next.call(v, ctx)
				}
			}
		}
	case []interface{}:
		for _, v := range castNode {
			if fn(v) {
				f.next.call(v, ctx)
			}
		}
	}
}
