// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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"
	"errors"
	"fmt"
	"reflect"
	"regexp"
	"sort"
	"strings"

	"cloud.google.com/go/internal/atomiccache"
	"cloud.google.com/go/internal/fields"
	pb "google.golang.org/genproto/googleapis/firestore/v1beta1"
)

// A FieldPath is a non-empty sequence of non-empty fields that reference a value.
//
// A FieldPath value should only be necessary if one of the field names contains
// one of the runes ".˜*/[]". Most methods accept a simpler form of field path
// as a string in which the individual fields are separated by dots.
// For example,
//   []string{"a", "b"}
// is equivalent to the string form
//   "a.b"
// but
//   []string{"*"}
// has no equivalent string form.
type FieldPath []string

// parseDotSeparatedString constructs a FieldPath from a string that separates
// path components with dots. Other than splitting at dots and checking for invalid
// characters, it ignores everything else about the string,
// including attempts to quote field path compontents. So "a.`b.c`.d" is parsed into
// four parts, "a", "`b", "c`" and "d".
func parseDotSeparatedString(s string) (FieldPath, error) {
	const invalidRunes = "~*/[]"
	if strings.ContainsAny(s, invalidRunes) {
		return nil, fmt.Errorf("firestore: %q contains an invalid rune (one of %s)", s, invalidRunes)
	}
	fp := FieldPath(strings.Split(s, "."))
	if err := fp.validate(); err != nil {
		return nil, err
	}
	return fp, nil
}

func (fp1 FieldPath) equal(fp2 FieldPath) bool {
	if len(fp1) != len(fp2) {
		return false
	}
	for i, c1 := range fp1 {
		if c1 != fp2[i] {
			return false
		}
	}
	return true
}

func (fp1 FieldPath) prefixOf(fp2 FieldPath) bool {
	return len(fp1) <= len(fp2) && fp1.equal(fp2[:len(fp1)])
}

// Lexicographic ordering.
func (fp1 FieldPath) less(fp2 FieldPath) bool {
	for i := range fp1 {
		switch {
		case i >= len(fp2):
			return false
		case fp1[i] < fp2[i]:
			return true
		case fp1[i] > fp2[i]:
			return false
		}
	}
	// fp1 and fp2 are equal up to len(fp1).
	return len(fp1) < len(fp2)
}

// validate checks the validity of fp and returns an error if it is invalid.
func (fp FieldPath) validate() error {
	if len(fp) == 0 {
		return errors.New("firestore: empty field path")
	}
	for _, c := range fp {
		if len(c) == 0 {
			return errors.New("firestore: empty component in field path")
		}
	}
	return nil
}

// with creates a new FieldPath consisting of fp followed by k.
func (fp FieldPath) with(k string) FieldPath {
	r := make(FieldPath, len(fp), len(fp)+1)
	copy(r, fp)
	return append(r, k)
}

// concat creates a new FieldPath consisting of fp1 followed by fp2.
func (fp1 FieldPath) concat(fp2 FieldPath) FieldPath {
	r := make(FieldPath, len(fp1)+len(fp2))
	copy(r, fp1)
	copy(r[len(fp1):], fp2)
	return r
}

// in reports whether fp is equal to one of the fps.
func (fp FieldPath) in(fps []FieldPath) bool {
	for _, e := range fps {
		if fp.equal(e) {
			return true
		}
	}
	return false
}

// checkNoDupOrPrefix checks whether any FieldPath is a prefix of (or equal to)
// another.
// It modifies the order of FieldPaths in its argument (via sorting).
func checkNoDupOrPrefix(fps []FieldPath) error {
	// Sort fps lexicographically.
	sort.Sort(byPath(fps))
	// Check adjacent pairs for prefix.
	for i := 1; i < len(fps); i++ {
		if fps[i-1].prefixOf(fps[i]) {
			return fmt.Errorf("field path %v cannot be used in the same update as %v", fps[i-1], fps[i])
		}
	}
	return nil
}

type byPath []FieldPath

func (b byPath) Len() int           { return len(b) }
func (b byPath) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b byPath) Less(i, j int) bool { return b[i].less(b[j]) }

// setAtPath sets val at the location in m specified by fp, creating sub-maps as
// needed. m must not be nil. fp is assumed to be valid.
func setAtPath(m map[string]*pb.Value, fp FieldPath, val *pb.Value) {
	if val == nil {
		return
	}
	if len(fp) == 1 {
		m[fp[0]] = val
	} else {
		v, ok := m[fp[0]]
		if !ok {
			v = &pb.Value{&pb.Value_MapValue{&pb.MapValue{map[string]*pb.Value{}}}}
			m[fp[0]] = v
		}
		// The type assertion below cannot fail, because setAtPath is only called
		// with either an empty map or one filled by setAtPath itself, and the
		// set of FieldPaths it is called with has been checked to make sure that
		// no path is the prefix of any other.
		setAtPath(v.GetMapValue().Fields, fp[1:], val)
	}
}

// getAtPath gets the value in data referred to by fp. The data argument can
// be a map or a struct.
// Compare with valueAtPath, which does the same thing for a document.
func getAtPath(v reflect.Value, fp FieldPath) (interface{}, error) {
	var err error
	for _, k := range fp {
		v, err = getAtField(v, k)
		if err != nil {
			return nil, err
		}
	}
	return v.Interface(), nil
}

// getAtField returns the equivalent of v[k], if v is a map, or v.k if v is a struct.
func getAtField(v reflect.Value, k string) (reflect.Value, error) {
	switch v.Kind() {
	case reflect.Map:
		if r := v.MapIndex(reflect.ValueOf(k)); r.IsValid() {
			return r, nil
		}

	case reflect.Struct:
		fm, err := fieldMap(v.Type())
		if err != nil {
			return reflect.Value{}, err
		}
		if f, ok := fm[k]; ok {
			return v.FieldByIndex(f.Index), nil
		}

	case reflect.Interface:
		return getAtField(v.Elem(), k)

	case reflect.Ptr:
		return getAtField(v.Elem(), k)
	}
	return reflect.Value{}, fmt.Errorf("firestore: no field %q for value %#v", k, v)
}

// fieldMapCache holds maps from from Firestore field name to struct field,
// keyed by struct type.
// TODO(jba): replace with sync.Map for Go 1.9.
var fieldMapCache atomiccache.Cache

func fieldMap(t reflect.Type) (map[string]fields.Field, error) {
	x := fieldMapCache.Get(t, func() interface{} {
		fieldList, err := fieldCache.Fields(t)
		if err != nil {
			return err
		}
		m := map[string]fields.Field{}
		for _, f := range fieldList {
			m[f.Name] = f
		}
		return m
	})
	if err, ok := x.(error); ok {
		return nil, err
	}
	return x.(map[string]fields.Field), nil
}

// toServiceFieldPath converts fp the form required by the Firestore service.
// It assumes fp has been validated.
func (fp FieldPath) toServiceFieldPath() string {
	cs := make([]string, len(fp))
	for i, c := range fp {
		cs[i] = toServiceFieldPathComponent(c)
	}
	return strings.Join(cs, ".")
}

func toServiceFieldPaths(fps []FieldPath) []string {
	var sfps []string
	for _, fp := range fps {
		sfps = append(sfps, fp.toServiceFieldPath())
	}
	return sfps
}

// Google SQL syntax for an unquoted field.
var unquotedFieldRegexp = regexp.MustCompile("^[A-Za-z_][A-Za-z_0-9]*$")

// toServiceFieldPathComponent returns a string that represents key and is a valid
// field path component.
func toServiceFieldPathComponent(key string) string {
	if unquotedFieldRegexp.MatchString(key) {
		return key
	}
	var buf bytes.Buffer
	buf.WriteRune('`')
	for _, r := range key {
		if r == '`' || r == '\\' {
			buf.WriteRune('\\')
		}
		buf.WriteRune(r)
	}
	buf.WriteRune('`')
	return buf.String()
}
