/*
 * Portions copyright 2019-present Open Networking Foundation
 * Original 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 order

import (
	"fmt"
	"reflect"
	"sort"
	"strings"
)

type Operation int

const (
	ASC Operation = iota
	DSC
)

type SortTerm struct {
	Op   Operation
	Name string
}

func (o Operation) String() string {
	switch o {
	default:
		fallthrough
	case ASC:
		return "ASC"
	case DSC:
		return "DSC"
	}
}

type Sorter []SortTerm

func split(term string) SortTerm {
	st := SortTerm{}
	if len(term) > 0 {
		switch term[0] {
		case '+':
			fallthrough
		case '>':
			st.Op = ASC
			st.Name = term[1:]
		case '-':
			fallthrough
		case '<':
			st.Op = DSC
			st.Name = term[1:]
		default:
			st.Op = ASC
			st.Name = term
		}
	} else {
		st.Op = ASC
		st.Name = term
	}
	return st
}

// Parse parses a comma separated list of filter terms
func Parse(spec string) (Sorter, error) {
	terms := strings.Split(spec, ",")
	s := make([]SortTerm, 0)
	for _, term := range terms {
		s = append(s, split(term))
	}

	return s, nil
}

func (s Sorter) Process(data interface{}) (interface{}, error) {
	slice := reflect.ValueOf(data)
	if slice.Kind() != reflect.Slice {
		return data, nil
	}

	sort.SliceStable(data, func(i, j int) bool {
		left := reflect.ValueOf(slice.Index(i).Interface())
		right := reflect.ValueOf(slice.Index(j).Interface())
		for _, term := range s {
			var fleft, fright reflect.Value
			if left.Kind() == reflect.Map {
				fleft = left.MapIndex(reflect.ValueOf(term.Name))
				fright = right.MapIndex(reflect.ValueOf(term.Name))
			} else {
				fleft = left.FieldByName(term.Name)
				fright = right.FieldByName(term.Name)
			}
			switch fleft.Kind() {
			case reflect.Uint:
				fallthrough
			case reflect.Uint8:
				fallthrough
			case reflect.Uint16:
				fallthrough
			case reflect.Uint32:
				fallthrough
			case reflect.Uint64:
				ileft := fleft.Uint()
				iright := fright.Uint()
				switch term.Op {
				case ASC:
					if ileft < iright {
						return true
					} else if ileft > iright {
						return false
					}
				case DSC:
					if ileft > iright {
						return true
					} else if ileft < iright {
						return false
					}
				}
			case reflect.Int:
				fallthrough
			case reflect.Int8:
				fallthrough
			case reflect.Int16:
				fallthrough
			case reflect.Int32:
				fallthrough
			case reflect.Int64:
				ileft := fleft.Int()
				iright := fright.Int()
				switch term.Op {
				case ASC:
					if ileft < iright {
						return true
					} else if ileft > iright {
						return false
					}
				case DSC:
					if ileft > iright {
						return true
					} else if ileft < iright {
						return false
					}
				}
			default:
				var sleft, sright string
				if left.Kind() == reflect.Map {
					sleft = fmt.Sprintf("%v", left.MapIndex(reflect.ValueOf(term.Name)))
					sright = fmt.Sprintf("%v", right.MapIndex(reflect.ValueOf(term.Name)))
				} else {
					sleft = fmt.Sprintf("%v", left.FieldByName(term.Name))
					sright = fmt.Sprintf("%v", right.FieldByName(term.Name))
				}
				diff := strings.Compare(sleft, sright)
				if term.Op != DSC {
					if diff == -1 {
						return true
					} else if diff == 1 {
						return false
					}
				} else {
					if diff == 1 {
						return true
					} else if diff == -1 {
						return false
					}
				}
			}
		}
		return false
	})

	return data, nil
}
