package rt_test

import (
	"fmt"
	"reflect"
	"sort"
	"testing"
	"time"

	"veyron.io/veyron/veyron2"
	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/naming"
	"veyron.io/veyron/veyron2/rt"
	"veyron.io/veyron/veyron2/security"

	_ "veyron.io/veyron/veyron/lib/testutil"
	"veyron.io/veyron/veyron/profiles"
	isecurity "veyron.io/veyron/veyron/runtimes/google/security"
	vsecurity "veyron.io/veyron/veyron/security"
)

type testService struct{}

func (*testService) EchoIDs(call ipc.ServerCall) (server, client []string) {
	return call.LocalID().Names(), call.RemoteID().Names()
}

type S []string

func newID(name string) security.PrivateID {
	id, err := isecurity.NewPrivateID(name, nil)
	if err != nil {
		panic(err)
	}
	return id
}

func bless(blessor security.PrivateID, blessee security.PublicID, name string) security.PublicID {
	blessedID, err := blessor.Bless(blessee, name, 5*time.Minute, nil)
	if err != nil {
		panic(err)
	}
	return blessedID
}

func add(store security.PublicIDStore, id security.PublicID, pattern security.BlessingPattern) {
	if err := store.Add(id, pattern); err != nil {
		panic(err)
	}
}

func call(r veyron2.Runtime, client ipc.Client, name string) (clientNames, serverNames []string, err error) {
	c, err := client.StartCall(r.NewContext(), name, "EchoIDs", nil)
	if err != nil {
		return nil, nil, err
	}
	if err := c.Finish(&serverNames, &clientNames); err != nil {
		return nil, nil, err
	}
	sort.Strings(clientNames)
	sort.Strings(serverNames)
	return
}

func TestClientServerIDs(t *testing.T) {
	stopServer := func(server ipc.Server) {
		if err := server.Stop(); err != nil {
			t.Fatalf("server.Stop failed: %s", err)
		}
	}
	var (
		self   = newID("self")
		google = newID("google")
		veyron = newID("veyron")

		googleGmailService   = bless(google, self.PublicID(), "gmail")
		googleYoutubeService = bless(google, self.PublicID(), "youtube")
		veyronService        = bless(veyron, self.PublicID(), "service")
		googleGmailClient    = bless(google, self.PublicID(), "gmailClient")
		googleYoutubeClient  = bless(google, self.PublicID(), "youtubeClient")
		veyronClient         = bless(veyron, self.PublicID(), "client")
	)
	isecurity.TrustIdentityProviders(google)
	isecurity.TrustIdentityProviders(veyron)

	serverR, err := rt.New(veyron2.RuntimeID(self))
	if err != nil {
		t.Fatalf("rt.New() failed: %s", err)
	}
	clientR, err := rt.New(veyron2.RuntimeID(self))
	if err != nil {
		t.Fatalf("rt.New() failed: %s", err)
	}

	// Add PublicIDs for running "google/gmail" and "google/youtube" services to
	// serverR's PublicIDStore. Since these PublicIDs are meant to be by
	// servers only they are tagged with "".
	add(serverR.PublicIDStore(), googleGmailService, "")
	add(serverR.PublicIDStore(), googleYoutubeService, "")
	// Add PublicIDs for communicating the "google/gmail" and "google/youtube" services
	// to the clientR's PublicIDStore.
	add(clientR.PublicIDStore(), googleGmailClient, "google/...")
	add(clientR.PublicIDStore(), googleYoutubeClient, "google/youtube")

	type testcase struct {
		server, client                   security.PublicID
		defaultPattern                   security.BlessingPattern
		wantServerNames, wantClientNames []string
	}
	tests := []testcase{
		{
			defaultPattern:  security.AllPrincipals,
			wantServerNames: S{"self", "google/gmail", "google/youtube"},
			wantClientNames: S{"self", "google/gmailClient", "google/youtubeClient"},
		},
		{
			defaultPattern:  "google/gmail",
			wantServerNames: S{"google/gmail"},
			wantClientNames: S{"self", "google/gmailClient"},
		},
		{
			defaultPattern:  "google/youtube",
			wantServerNames: S{"google/youtube"},
			wantClientNames: S{"self", "google/gmailClient", "google/youtubeClient"},
		},
		{
			server:          veyronService,
			defaultPattern:  security.AllPrincipals,
			wantServerNames: S{"veyron/service"},
			wantClientNames: S{"self"},
		},
		{
			client:          veyronClient,
			defaultPattern:  security.AllPrincipals,
			wantServerNames: S{"self", "google/gmail", "google/youtube"},
			wantClientNames: S{"veyron/client"},
		},
		{
			server:          veyronService,
			client:          veyronClient,
			defaultPattern:  security.AllPrincipals,
			wantServerNames: S{"veyron/service"},
			wantClientNames: S{"veyron/client"},
		},
	}
	name := func(t testcase) string {
		return fmt.Sprintf("TestCase{clientPublicIDStore: %v, serverPublicIDStore: %v, client option: %v, server option: %v}", clientR.PublicIDStore(), serverR.PublicIDStore(), t.client, t.server)
	}
	for _, test := range tests {
		if err := serverR.PublicIDStore().SetDefaultBlessingPattern(test.defaultPattern); err != nil {
			t.Errorf("serverR.PublicIDStore.SetDefaultBlessingPattern failed: %s", err)
			continue
		}
		server, err := serverR.NewServer(veyron2.LocalID(test.server))
		if err != nil {
			t.Errorf("serverR.NewServer(...) failed: %s", err)
			continue
		}
		endpoint, err := server.ListenX(profiles.LocalListenSpec)
		if err != nil {
			t.Errorf("error listening to service: ", err)
			continue
		}
		defer stopServer(server)
		if err := server.Serve("", ipc.LeafDispatcher(&testService{},
			vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
				security.AllPrincipals: security.AllLabels,
			}}))); err != nil {
			t.Errorf("error serving service: ", err)
			continue
		}

		client, err := clientR.NewClient(veyron2.LocalID(test.client))
		if err != nil {
			t.Errorf("clientR.NewClient(...) failed: %s", err)
			continue
		}
		defer client.Close()

		clientNames, serverNames, err := call(clientR, client, naming.JoinAddressName(fmt.Sprintf("%v", endpoint), ""))
		if err != nil {
			t.Errorf("IPC failed: %s", err)
			continue
		}
		sort.Strings(test.wantClientNames)
		sort.Strings(test.wantServerNames)
		if !reflect.DeepEqual(clientNames, test.wantClientNames) {
			t.Errorf("TestCase: %s, Got clientNames: %v, want: %v", name(test), clientNames, test.wantClientNames)
			continue
		}
		if !reflect.DeepEqual(serverNames, test.wantServerNames) {
			t.Errorf("TestCase: %s, Got serverNames: %v, want: %v", name(test), serverNames, test.wantServerNames)
			continue
		}
	}
}
