// Copyright 2018 Google LLC
//
// 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 firestore

import (
	"bytes"
	"fmt"
	"math"
	"sort"
	"strings"

	tspb "github.com/golang/protobuf/ptypes/timestamp"
	pb "google.golang.org/genproto/googleapis/firestore/v1beta1"
)

// Returns a negative number, zero, or a positive number depending on whether a is
// less than, equal to, or greater than b according to Firestore's ordering of
// values.
func compareValues(a, b *pb.Value) int {
	ta := typeOrder(a)
	tb := typeOrder(b)
	if ta != tb {
		return compareInt64s(int64(ta), int64(tb))
	}
	switch a := a.ValueType.(type) {
	case *pb.Value_NullValue:
		return 0 // nulls are equal

	case *pb.Value_BooleanValue:
		av := a.BooleanValue
		bv := b.GetBooleanValue()
		switch {
		case av && !bv:
			return 1
		case bv && !av:
			return -1
		default:
			return 0
		}

	case *pb.Value_IntegerValue:
		return compareNumbers(float64(a.IntegerValue), toFloat(b))

	case *pb.Value_DoubleValue:
		return compareNumbers(a.DoubleValue, toFloat(b))

	case *pb.Value_TimestampValue:
		return compareTimestamps(a.TimestampValue, b.GetTimestampValue())

	case *pb.Value_StringValue:
		return strings.Compare(a.StringValue, b.GetStringValue())

	case *pb.Value_BytesValue:
		return bytes.Compare(a.BytesValue, b.GetBytesValue())

	case *pb.Value_ReferenceValue:
		return compareReferences(a.ReferenceValue, b.GetReferenceValue())

	case *pb.Value_GeoPointValue:
		ag := a.GeoPointValue
		bg := b.GetGeoPointValue()
		if ag.Latitude != bg.Latitude {
			return compareFloat64s(ag.Latitude, bg.Latitude)
		}
		return compareFloat64s(ag.Longitude, bg.Longitude)

	case *pb.Value_ArrayValue:
		return compareArrays(a.ArrayValue.Values, b.GetArrayValue().Values)

	case *pb.Value_MapValue:
		return compareMaps(a.MapValue.Fields, b.GetMapValue().Fields)

	default:
		panic(fmt.Sprintf("bad value type: %v", a))
	}
}

// Treats NaN as less than any non-NaN.
func compareNumbers(a, b float64) int {
	switch {
	case math.IsNaN(a):
		if math.IsNaN(b) {
			return 0
		}
		return -1
	case math.IsNaN(b):
		return 1
	default:
		return compareFloat64s(a, b)
	}
}

// Return v as a float64, assuming it's an Integer or Double.
func toFloat(v *pb.Value) float64 {
	if x, ok := v.ValueType.(*pb.Value_IntegerValue); ok {
		return float64(x.IntegerValue)
	}
	return v.GetDoubleValue()
}

func compareTimestamps(a, b *tspb.Timestamp) int {
	if c := compareInt64s(a.Seconds, b.Seconds); c != 0 {
		return c
	}
	return compareInt64s(int64(a.Nanos), int64(b.Nanos))
}

func compareReferences(a, b string) int {
	// Compare path components lexicographically.
	pa := strings.Split(a, "/")
	pb := strings.Split(b, "/")
	return compareSequences(len(pa), len(pb), func(i int) int {
		return strings.Compare(pa[i], pb[i])
	})
}

func compareArrays(a, b []*pb.Value) int {
	return compareSequences(len(a), len(b), func(i int) int {
		return compareValues(a[i], b[i])
	})
}

func compareMaps(a, b map[string]*pb.Value) int {
	sortedKeys := func(m map[string]*pb.Value) []string {
		var ks []string
		for k := range m {
			ks = append(ks, k)
		}
		sort.Strings(ks)
		return ks
	}

	aks := sortedKeys(a)
	bks := sortedKeys(b)
	return compareSequences(len(aks), len(bks), func(i int) int {
		if c := strings.Compare(aks[i], bks[i]); c != 0 {
			return c
		}
		k := aks[i]
		return compareValues(a[k], b[k])
	})
}

func compareSequences(len1, len2 int, compare func(int) int) int {
	for i := 0; i < len1 && i < len2; i++ {
		if c := compare(i); c != 0 {
			return c
		}
	}
	return compareInt64s(int64(len1), int64(len2))
}

func compareFloat64s(a, b float64) int {
	switch {
	case a < b:
		return -1
	case a > b:
		return 1
	default:
		return 0
	}
}

func compareInt64s(a, b int64) int {
	switch {
	case a < b:
		return -1
	case a > b:
		return 1
	default:
		return 0
	}
}

// Return an integer corresponding to the type of value stored in v, such that
// comparing the resulting integers gives the Firestore ordering for types.
func typeOrder(v *pb.Value) int {
	switch v.ValueType.(type) {
	case *pb.Value_NullValue:
		return 0
	case *pb.Value_BooleanValue:
		return 1
	case *pb.Value_IntegerValue:
		return 2
	case *pb.Value_DoubleValue:
		return 2
	case *pb.Value_TimestampValue:
		return 3
	case *pb.Value_StringValue:
		return 4
	case *pb.Value_BytesValue:
		return 5
	case *pb.Value_ReferenceValue:
		return 6
	case *pb.Value_GeoPointValue:
		return 7
	case *pb.Value_ArrayValue:
		return 8
	case *pb.Value_MapValue:
		return 9
	default:
		panic(fmt.Sprintf("bad value type: %v", v))
	}
}
