// Copyright 2016 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package iterator_test

import (
	"context"
	"encoding/json"
	"math"
	"reflect"
	"testing"

	"google.golang.org/api/iterator"
	itest "google.golang.org/api/iterator/testing"
)

// Service represents the implementation of a Google API's List method.
// We want to test against a large range of possible valid behaviors.
// All the behaviors this can generate are valid under the spec for
// Google API paging.
type service struct {
	// End of the sequence. end-1 is the last value returned.
	end int
	// Maximum number of items to return in one RPC. Also the default page size.
	// If zero, max is unlimited.
	max int
	// If true, return two empty pages before each RPC that returns items, and
	// two zero pages at the end. E.g. if end = 5, max = 2 and the pageSize
	// parameter to List is zero, then the number of items returned in
	// successive RPCS is:
	//    0 0 2 0 0 2 0 0 1 0 0
	// Note that this implies that the RPC returning the last items will have a
	// non-empty page token.
	zeroes bool
}

// List simulates an API List RPC. It returns integers in the range [0, s.end).
func (s *service) List(pageSize int, pageToken string) ([]int, string, error) {
	max := s.max
	if max == 0 {
		max = math.MaxInt
	}
	// Never give back any more than s.max.
	if pageSize <= 0 || pageSize > max {
		pageSize = max
	}
	state := &listState{}
	if pageToken != "" {
		if err := json.Unmarshal([]byte(pageToken), state); err != nil {
			return nil, "", err
		}
	}
	ints := state.advance(pageSize, s.end, s.zeroes)
	if state.Start == s.end && (!s.zeroes || state.NumZeroes == 2) {
		pageToken = ""
	} else {
		bytes, err := json.Marshal(state)
		if err != nil {
			return nil, "", err
		}
		pageToken = string(bytes)
	}
	return ints, pageToken, nil
}

type listState struct {
	Start     int // where to start this page
	NumZeroes int // number of consecutive empty pages before this
}

func (s *listState) advance(pageSize, end int, zeroes bool) []int {
	var page []int
	if zeroes && s.NumZeroes != 2 {
		// Return a zero page.
	} else {
		for i := s.Start; i < end && len(page) < pageSize; i++ {
			page = append(page, i)
		}
	}
	s.Start += len(page)
	if len(page) == 0 {
		s.NumZeroes++
	} else {
		s.NumZeroes = 0
	}
	return page
}

func TestServiceList(t *testing.T) {
	for _, test := range []struct {
		svc      service
		pageSize int
		want     [][]int
	}{
		{service{end: 0}, 0, [][]int{nil}},
		{service{end: 5}, 0, [][]int{{0, 1, 2, 3, 4}}},
		{service{end: 5}, 8, [][]int{{0, 1, 2, 3, 4}}},
		{service{end: 5}, 2, [][]int{{0, 1}, {2, 3}, {4}}},
		{service{end: 5, max: 2}, 0, [][]int{{0, 1}, {2, 3}, {4}}},
		{service{end: 5, max: 2}, 1, [][]int{{0}, {1}, {2}, {3}, {4}}},
		{service{end: 5, max: 2}, 10, [][]int{{0, 1}, {2, 3}, {4}}},
		{service{end: 5, zeroes: true}, 0, [][]int{nil, nil, {0, 1, 2, 3, 4}, nil, nil}},
		{service{end: 5, max: 3, zeroes: true}, 0, [][]int{nil, nil, {0, 1, 2}, nil, nil, {3, 4}, nil, nil}},
	} {
		var got [][]int
		token := ""
		for {
			items, nextToken, err := test.svc.List(test.pageSize, token)
			if err != nil {
				t.Fatalf("%v, %d: %v", test.svc, test.pageSize, err)
			}
			got = append(got, items)
			if nextToken == "" {
				break
			}
			token = nextToken
		}
		if !reflect.DeepEqual(got, test.want) {
			t.Errorf("%v, %d: got %v, want %v", test.svc, test.pageSize, got, test.want)
		}
	}
}

type Client struct{ s *service }

// ItemIterator is a sample implementation of a standard iterator.
type ItemIterator struct {
	pageInfo *iterator.PageInfo
	nextFunc func() error
	s        *service
	items    []int
}

// PageInfo returns a PageInfo, which supports pagination.
func (it *ItemIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }

// Items is a sample implementation of an iterator-creating method.
func (c *Client) Items(ctx context.Context) *ItemIterator {
	it := &ItemIterator{s: c.s}
	it.pageInfo, it.nextFunc = iterator.NewPageInfo(
		it.fetch,
		func() int { return len(it.items) },
		func() interface{} { b := it.items; it.items = nil; return b })
	return it
}

func (it *ItemIterator) fetch(pageSize int, pageToken string) (string, error) {
	items, tok, err := it.s.List(pageSize, pageToken)
	it.items = append(it.items, items...)
	return tok, err
}

func (it *ItemIterator) Next() (int, error) {
	if err := it.nextFunc(); err != nil {
		return 0, err
	}
	item := it.items[0]
	it.items = it.items[1:]
	return item, nil
}

func TestNext(t *testing.T) {
	// Test the iterator's Next method with a variety of different service behaviors.
	// This is primarily a test of PageInfo.next.
	for _, svc := range []service{
		{end: 0},
		{end: 5},
		{end: 5, max: 1},
		{end: 5, max: 2},
		{end: 5, zeroes: true},
		{end: 5, max: 2, zeroes: true},
	} {
		client := &Client{&svc}

		msg, ok := itest.TestIterator(
			seq(0, svc.end),
			func() interface{} { return client.Items(ctx) },
			func(it interface{}) (interface{}, error) { return it.(*ItemIterator).Next() })
		if !ok {
			t.Errorf("%+v: %s", svc, msg)
		}
	}
}

// TODO(jba): test setting PageInfo.MaxSize
// TODO(jba): test setting PageInfo.Token

// Verify that, for an iterator that uses PageInfo.next to implement its Next
// method, using Next and NextPage together result in an error.
func TestNextWithNextPage(t *testing.T) {
	client := &Client{&service{end: 11}}
	var items []int

	// Calling Next before NextPage.
	it := client.Items(ctx)
	it.Next()
	_, err := iterator.NewPager(it, 1, "").NextPage(&items)
	if err == nil {
		t.Error("NextPage after Next: got nil, want error")
	}
	_, err = it.Next()
	if err == nil {
		t.Error("Next after NextPage: got nil, want error")
	}

	// Next between two calls to NextPage.
	it = client.Items(ctx)
	p := iterator.NewPager(it, 1, "")
	p.NextPage(&items)
	_, err = it.Next()
	if err == nil {
		t.Error("Next after NextPage: got nil, want error")
	}
	_, err = p.NextPage(&items)
	if err == nil {
		t.Error("second NextPage after Next: got nil, want error")
	}
}

// Verify that we turn various potential reflection panics into errors.
func TestNextPageReflectionErrors(t *testing.T) {
	client := &Client{&service{end: 1}}
	p := iterator.NewPager(client.Items(ctx), 1, "")

	// Passing the nil interface value.
	_, err := p.NextPage(nil)
	if err == nil {
		t.Error("nil: got nil, want error")
	}

	// Passing a non-slice.
	_, err = p.NextPage(17)
	if err == nil {
		t.Error("non-slice: got nil, want error")
	}

	// Passing a slice of the wrong type.
	var bools []bool
	_, err = p.NextPage(&bools)
	if err == nil {
		t.Error("wrong type: got nil, want error")
	}

	// Using a slice of the right type, but not passing a pointer to it.
	var ints []int
	_, err = p.NextPage(ints)
	if err == nil {
		t.Error("not a pointer: got nil, want error")
	}
}

// seq returns a slice containing the values in [from, to).
func seq(from, to int) []int {
	var r []int
	for i := from; i < to; i++ {
		r = append(r, i)
	}
	return r
}
