package devices

import (
	"testing"
	"time"

	"code.secondbit.org/uuid.hg"
	"golang.org/x/net/context"
)

var storers []Storer

func compareDevices(device1, device2 Device) (ok bool, field string, expected, result interface{}) {
	if !device1.ID.Equal(device2.ID) {
		return false, "ID", device1.ID, device2.ID
	}
	if device1.Name != device2.Name {
		return false, "Name", device1.Name, device2.Name
	}
	if !device1.Owner.Equal(device2.Owner) {
		return false, "Owner", device1.Owner, device2.Owner
	}
	if device1.Type != device2.Type {
		return false, "Type", device1.Type, device2.Type
	}
	if !device1.Created.Equal(device2.Created) {
		return false, "Created", device1.Created, device2.Created
	}
	if !device1.LastSeen.Equal(device2.LastSeen) {
		return false, "LastSeen", device1.LastSeen, device2.LastSeen
	}
	if device1.PushToken != device2.PushToken {
		return false, "PushToken", device1.PushToken, device2.PushToken
	}
	return true, "", nil, nil
}

func TestGetDevicesHappyPath(t *testing.T) {
	for _, storer := range storers {
		storer, err := storer.Factory(context.TODO())
		if err != nil {
			t.Fatalf("Fatal error creating %T: %+v\n", storer, err)
		}

		devices := []Device{
			{ID: uuid.NewID(), Name: "Test 1", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
			{ID: uuid.NewID(), Name: "Test 2", Owner: uuid.NewID(), Type: TypeAndroidTablet, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
			{ID: uuid.NewID(), Name: "Test 3", Owner: uuid.NewID(), Type: TypeChromeExtension, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
		}

		err = storer.CreateDevices(devices, context.TODO())
		if err != nil {
			t.Errorf("Error creating devices in %T: %+v\n", err)
		}

		ids := make([]uuid.ID, 0, len(devices))
		for _, device := range devices {
			ids = append(ids, device.ID)
		}

		results, err := storer.GetDevices(ids, context.TODO())
		if err != nil {
			t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
		}
		for _, device := range devices {
			d, returned := results[device.ID.String()]
			if !returned {
				t.Errorf("Expected device %s to be in results from %T, but wasn't present\n", device.Name, storer)
			}
			ok, field, expected, result := compareDevices(device, d)
			if !ok {
				t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, device.Name, expected, result, storer)
			}
		}
		err = storer.Destroy(context.TODO())
		if err != nil {
			t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
		}
	}
}
