// Copyright 2016 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 pubsub

import (
	"testing"

	"cloud.google.com/go/internal/testutil"

	"golang.org/x/net/context"

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

type subListService struct {
	service
	subs []string
	err  error

	t *testing.T // for error logging.
}

func (s *subListService) newNextStringFunc() nextStringFunc {
	return func() (string, error) {
		if len(s.subs) == 0 {
			return "", iterator.Done
		}
		sn := s.subs[0]
		s.subs = s.subs[1:]
		return sn, s.err
	}
}

func (s *subListService) listProjectSubscriptions(ctx context.Context, projName string) nextStringFunc {
	if projName != "projects/projid" {
		s.t.Fatalf("unexpected call: projName: %q", projName)
		return nil
	}
	return s.newNextStringFunc()
}

func (s *subListService) listTopicSubscriptions(ctx context.Context, topicName string) nextStringFunc {
	if topicName != "projects/projid/topics/topic" {
		s.t.Fatalf("unexpected call: topicName: %q", topicName)
		return nil
	}
	return s.newNextStringFunc()
}

// All returns the remaining subscriptions from this iterator.
func slurpSubs(it *SubscriptionIterator) ([]*Subscription, error) {
	var subs []*Subscription
	for {
		switch sub, err := it.Next(); err {
		case nil:
			subs = append(subs, sub)
		case iterator.Done:
			return subs, nil
		default:
			return nil, err
		}
	}
}

func TestSubscriptionID(t *testing.T) {
	const id = "id"
	serv := &subListService{
		subs: []string{"projects/projid/subscriptions/s1", "projects/projid/subscriptions/s2"},
		t:    t,
	}
	c := &Client{projectID: "projid", s: serv}
	s := c.Subscription(id)
	if got, want := s.ID(), id; got != want {
		t.Errorf("Subscription.ID() = %q; want %q", got, want)
	}
	want := []string{"s1", "s2"}
	subs, err := slurpSubs(c.Subscriptions(context.Background()))
	if err != nil {
		t.Errorf("error listing subscriptions: %v", err)
	}
	for i, s := range subs {
		if got, want := s.ID(), want[i]; got != want {
			t.Errorf("Subscription.ID() = %q; want %q", got, want)
		}
	}
}

func TestListProjectSubscriptions(t *testing.T) {
	snames := []string{"projects/projid/subscriptions/s1", "projects/projid/subscriptions/s2",
		"projects/projid/subscriptions/s3"}
	s := &subListService{subs: snames, t: t}
	c := &Client{projectID: "projid", s: s}
	subs, err := slurpSubs(c.Subscriptions(context.Background()))
	if err != nil {
		t.Errorf("error listing subscriptions: %v", err)
	}
	got := subNames(subs)
	want := []string{
		"projects/projid/subscriptions/s1",
		"projects/projid/subscriptions/s2",
		"projects/projid/subscriptions/s3"}
	if !testutil.Equal(got, want) {
		t.Errorf("sub list: got: %v, want: %v", got, want)
	}
	if len(s.subs) != 0 {
		t.Errorf("outstanding subs: %v", s.subs)
	}
}

func TestListTopicSubscriptions(t *testing.T) {
	snames := []string{"projects/projid/subscriptions/s1", "projects/projid/subscriptions/s2",
		"projects/projid/subscriptions/s3"}
	s := &subListService{subs: snames, t: t}
	c := &Client{projectID: "projid", s: s}
	subs, err := slurpSubs(c.Topic("topic").Subscriptions(context.Background()))
	if err != nil {
		t.Errorf("error listing subscriptions: %v", err)
	}
	got := subNames(subs)
	want := []string{
		"projects/projid/subscriptions/s1",
		"projects/projid/subscriptions/s2",
		"projects/projid/subscriptions/s3"}
	if !testutil.Equal(got, want) {
		t.Errorf("sub list: got: %v, want: %v", got, want)
	}
	if len(s.subs) != 0 {
		t.Errorf("outstanding subs: %v", s.subs)
	}
}

func subNames(subs []*Subscription) []string {
	var names []string
	for _, sub := range subs {
		names = append(names, sub.name)
	}
	return names
}
