// 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 (
	"reflect"
	"sort"
	"testing"
	"time"

	pb "google.golang.org/genproto/googleapis/firestore/v1beta1"

	"golang.org/x/net/context"
	"google.golang.org/genproto/googleapis/type/latlng"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

var (
	writeResultForSet    = &WriteResult{UpdateTime: aTime}
	commitResponseForSet = &pb.CommitResponse{
		WriteResults: []*pb.WriteResult{{UpdateTime: aTimestamp}},
	}
)

func TestDocGet(t *testing.T) {
	ctx := context.Background()
	c, srv := newMock(t)
	path := "projects/projectID/databases/(default)/documents/C/a"
	pdoc := &pb.Document{
		Name:       path,
		CreateTime: aTimestamp,
		UpdateTime: aTimestamp,
		Fields:     map[string]*pb.Value{"f": intval(1)},
	}
	srv.addRPC(&pb.BatchGetDocumentsRequest{
		Database:  c.path(),
		Documents: []string{path},
	}, []interface{}{
		&pb.BatchGetDocumentsResponse{
			Result:   &pb.BatchGetDocumentsResponse_Found{pdoc},
			ReadTime: aTimestamp2,
		},
	})
	ref := c.Collection("C").Doc("a")
	gotDoc, err := ref.Get(ctx)
	if err != nil {
		t.Fatal(err)
	}
	wantDoc := &DocumentSnapshot{
		Ref:        ref,
		CreateTime: aTime,
		UpdateTime: aTime,
		ReadTime:   aTime2,
		proto:      pdoc,
		c:          c,
	}
	if !testEqual(gotDoc, wantDoc) {
		t.Fatalf("\ngot  %+v\nwant %+v", gotDoc, wantDoc)
	}

	path2 := "projects/projectID/databases/(default)/documents/C/b"
	srv.addRPC(
		&pb.BatchGetDocumentsRequest{
			Database:  c.path(),
			Documents: []string{path2},
		}, []interface{}{
			&pb.BatchGetDocumentsResponse{
				Result:   &pb.BatchGetDocumentsResponse_Missing{path2},
				ReadTime: aTimestamp3,
			},
		})
	_, err = c.Collection("C").Doc("b").Get(ctx)
	if grpc.Code(err) != codes.NotFound {
		t.Errorf("got %v, want NotFound", err)
	}
}

func TestDocSet(t *testing.T) {
	// Most tests for Set are in the cross-language tests.
	ctx := context.Background()
	c, srv := newMock(t)

	doc := c.Collection("C").Doc("d")
	// Merge with a struct and FieldPaths.
	srv.addRPC(&pb.CommitRequest{
		Database: "projects/projectID/databases/(default)",
		Writes: []*pb.Write{
			{
				Operation: &pb.Write_Update{
					Update: &pb.Document{
						Name: "projects/projectID/databases/(default)/documents/C/d",
						Fields: map[string]*pb.Value{
							"*": mapval(map[string]*pb.Value{
								"~": boolval(true),
							}),
						},
					},
				},
				UpdateMask: &pb.DocumentMask{FieldPaths: []string{"`*`.`~`"}},
			},
		},
	}, commitResponseForSet)
	data := struct {
		A map[string]bool `firestore:"*"`
	}{A: map[string]bool{"~": true}}
	wr, err := doc.Set(ctx, data, Merge([]string{"*", "~"}))
	if err != nil {
		t.Fatal(err)
	}
	if !testEqual(wr, writeResultForSet) {
		t.Errorf("got %v, want %v", wr, writeResultForSet)
	}

	// MergeAll cannot be used with structs.
	_, err = doc.Set(ctx, data, MergeAll)
	if err == nil {
		t.Errorf("got nil, want error")
	}
}

func TestDocCreate(t *testing.T) {
	// Verify creation with structs. In particular, make sure zero values
	// are handled well.
	// Other tests for Create are handled by the cross-language tests.
	ctx := context.Background()
	c, srv := newMock(t)

	type create struct {
		Time  time.Time
		Bytes []byte
		Geo   *latlng.LatLng
	}
	srv.addRPC(
		&pb.CommitRequest{
			Database: "projects/projectID/databases/(default)",
			Writes: []*pb.Write{
				{
					Operation: &pb.Write_Update{
						Update: &pb.Document{
							Name: "projects/projectID/databases/(default)/documents/C/d",
							Fields: map[string]*pb.Value{
								"Time":  tsval(time.Time{}),
								"Bytes": bytesval(nil),
								"Geo":   nullValue,
							},
						},
					},
					CurrentDocument: &pb.Precondition{
						ConditionType: &pb.Precondition_Exists{false},
					},
				},
			},
		},
		commitResponseForSet,
	)
	_, err := c.Collection("C").Doc("d").Create(ctx, &create{})
	if err != nil {
		t.Fatal(err)
	}
}

func TestDocDelete(t *testing.T) {
	ctx := context.Background()
	c, srv := newMock(t)
	srv.addRPC(
		&pb.CommitRequest{
			Database: "projects/projectID/databases/(default)",
			Writes: []*pb.Write{
				{Operation: &pb.Write_Delete{"projects/projectID/databases/(default)/documents/C/d"}},
			},
		},
		&pb.CommitResponse{
			WriteResults: []*pb.WriteResult{{}},
		})
	wr, err := c.Collection("C").Doc("d").Delete(ctx)
	if err != nil {
		t.Fatal(err)
	}
	if !testEqual(wr, &WriteResult{}) {
		t.Errorf("got %+v, want %+v", wr, writeResultForSet)
	}
}

var (
	testData   = map[string]interface{}{"a": 1}
	testFields = map[string]*pb.Value{"a": intval(1)}
)

// Update is tested by the cross-language tests.

func TestFPVsFromData(t *testing.T) {
	type S struct{ X int }

	for _, test := range []struct {
		in   interface{}
		want []fpv
	}{
		{
			in:   nil,
			want: []fpv{{nil, nil}},
		},
		{
			in:   map[string]interface{}{"a": nil},
			want: []fpv{{[]string{"a"}, nil}},
		},
		{
			in:   map[string]interface{}{"a": 1},
			want: []fpv{{[]string{"a"}, 1}},
		},
		{
			in: map[string]interface{}{
				"a": 1,
				"b": map[string]interface{}{"c": 2},
			},
			want: []fpv{{[]string{"a"}, 1}, {[]string{"b", "c"}, 2}},
		},
		{
			in:   map[string]interface{}{"s": &S{X: 3}},
			want: []fpv{{[]string{"s"}, &S{X: 3}}},
		},
	} {
		var got []fpv
		fpvsFromData(reflect.ValueOf(test.in), nil, &got)
		sort.Sort(byFieldPath(got))
		if !testEqual(got, test.want) {
			t.Errorf("%+v: got %v, want %v", test.in, got, test.want)
		}
	}
}

type byFieldPath []fpv

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

func commitRequestForSet() *pb.CommitRequest {
	return &pb.CommitRequest{
		Database: "projects/projectID/databases/(default)",
		Writes: []*pb.Write{
			{
				Operation: &pb.Write_Update{
					Update: &pb.Document{
						Name:   "projects/projectID/databases/(default)/documents/C/d",
						Fields: testFields,
					},
				},
			},
		},
	}
}

func TestUpdateProcess(t *testing.T) {
	for _, test := range []struct {
		in      Update
		want    fpv
		wantErr bool
	}{
		{
			in:   Update{Path: "a", Value: 1},
			want: fpv{fieldPath: []string{"a"}, value: 1},
		},
		{
			in:   Update{Path: "c.d", Value: Delete},
			want: fpv{fieldPath: []string{"c", "d"}, value: Delete},
		},
		{
			in:   Update{FieldPath: []string{"*", "~"}, Value: ServerTimestamp},
			want: fpv{fieldPath: []string{"*", "~"}, value: ServerTimestamp},
		},
		{
			in:      Update{Path: "*"},
			wantErr: true, // bad rune in path
		},
		{
			in:      Update{Path: "a", FieldPath: []string{"b"}},
			wantErr: true, // both Path and FieldPath
		},
		{
			in:      Update{Value: 1},
			wantErr: true, // neither Path nor FieldPath
		},
		{
			in:      Update{FieldPath: []string{"", "a"}},
			wantErr: true, // empty FieldPath component
		},
	} {
		got, err := test.in.process()
		if test.wantErr {
			if err == nil {
				t.Errorf("%+v: got nil, want error", test.in)
			}
		} else if err != nil {
			t.Errorf("%+v: got error %v, want nil", test.in, err)
		} else if !testEqual(got, test.want) {
			t.Errorf("%+v: got %+v, want %+v", test.in, got, test.want)
		}
	}
}
