/*
 * Copyright 2019-present Ciena Corporation
 *
 * 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 filter

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

type Operation int

const (
	UK Operation = iota
	EQ
	NE
	GT
	LT
	GE
	LE
	RE
)

func toOp(op string) Operation {
	switch op {
	case "=":
		return EQ
	case "!=":
		return NE
	case ">":
		return GT
	case "<":
		return LT
	case ">=":
		return GE
	case "<=":
		return LE
	case "~":
		return RE
	default:
		return UK
	}
}

type FilterTerm struct {
	Op    Operation
	Value string
	re    *regexp.Regexp
}

type Filter map[string]FilterTerm

var termRE = regexp.MustCompile(`^\s*([a-zA-Z_][.a-zA-Z0-9_]*)\s*(~|<=|>=|<|>|!=|=)\s*(.+)\s*$`)

// Parse parses a comma separated list of filter terms
func Parse(spec string) (Filter, error) {
	filter := make(map[string]FilterTerm)
	terms := strings.Split(spec, ",")
	var err error

	// Each term is in the form <key><op><value>
	for _, term := range terms {
		parts := termRE.FindAllStringSubmatch(term, -1)
		if parts == nil {
			return nil, fmt.Errorf("Unable to parse filter term '%s'", term)
		}
		ft := FilterTerm{
			Op:    toOp(parts[0][2]),
			Value: parts[0][3],
		}
		if ft.Op == RE {
			ft.re, err = regexp.Compile(ft.Value)
			if err != nil {
				return nil, fmt.Errorf("Unable to parse regexp filter value '%s'", ft.Value)
			}
		}
		filter[parts[0][1]] = ft
	}
	return filter, nil
}

func (f Filter) Process(data interface{}) (interface{}, error) {
	slice := reflect.ValueOf(data)
	if slice.Kind() != reflect.Slice {
		match, err := f.Evaluate(data)
		if err != nil {
			return nil, err
		}
		if match {
			return data, nil
		}
		return nil, nil
	}

	var result []interface{}

	for i := 0; i < slice.Len(); i++ {
		match, err := f.Evaluate(slice.Index(i).Interface())
		if err != nil {
			return nil, err
		}
		if match {
			result = append(result, slice.Index(i).Interface())
		}
	}

	return result, nil
}

// returns False if the filter does not match
// returns true if the filter does match or the operation is unsupported
func testField(v FilterTerm, field reflect.Value) bool {
	switch v.Op {
	case RE:
		if !v.re.MatchString(fmt.Sprintf("%v", field)) {
			return false
		}
	case EQ:
		// This seems to work for most comparisons
		if fmt.Sprintf("%v", field) != v.Value {
			return false
		}
	case NE:
		// This seems to work for most comparisons
		if fmt.Sprintf("%v", field) == v.Value {
			return false
		}
	default:
		// For unsupported operations, always pass
	}

	return true
}

func (f Filter) EvaluateTerm(k string, v FilterTerm, val reflect.Value, recurse bool) (bool, error) {
	// If we have been given a pointer, then deference it
	if val.Kind() == reflect.Ptr {
		val = reflect.Indirect(val)
	}

	// If the user gave us an explicitly named dotted field, then split it
	if strings.Contains(k, ".") {
		parts := strings.SplitN(k, ".", 2)
		if val.Kind() != reflect.Struct {
			return false, fmt.Errorf("Dotted field name specified in filter did not resolve to a valid field")
		}
		field := val.FieldByName(parts[0])
		if !field.IsValid() {
			return false, fmt.Errorf("Failed to find dotted field %s while filtering", parts[0])
		}
		return f.EvaluateTerm(parts[1], v, field, false)
	}

	if val.Kind() != reflect.Struct {
		return false, fmt.Errorf("Dotted field name specified in filter did not resolve to a valid field")
	}

	field := val.FieldByName(k)
	if !field.IsValid() {
		return false, fmt.Errorf("Failed to find field %s while filtering", k)
	}

	if (field.Kind() == reflect.Slice) || (field.Kind() == reflect.Array) {
		// For an array, check to see if any item matches
		someMatch := false
		for i := 0; i < field.Len(); i++ {
			arrayElem := field.Index(i)
			if testField(v, arrayElem) {
				someMatch = true
			}
		}
		if !someMatch {
			//if recurse && val.Kind() == reflect.Struct {
			//    TODO: implement automatic recursion when the user did not
			//          use a dotted notation. Go through the list of fields
			//          in the struct, recursively check each one.
			//}
			return false, nil
		}
	} else {
		if !testField(v, field) {
			return false, nil
		}
	}

	return true, nil
}

func (f Filter) Evaluate(item interface{}) (bool, error) {
	val := reflect.ValueOf(item)

	for k, v := range f {
		matches, err := f.EvaluateTerm(k, v, val, true)
		if err != nil {
			return false, err
		}
		if !matches {
			// If any of the filter fail, the overall match fails
			return false, nil
		}
	}

	return true, nil
}
