package storage

import (
	"reflect"

	"github.com/juju/errors"
	. "github.com/pingcap/check"
	"github.com/pingcap/schrodinger/pkg/types"
)

var _ = Suite(&objectSuite{})

type objectSuite struct {
	store *Storage
}

func (t *objectSuite) SetUpTest(c *C) {
	t.store = setupStore("object")
}

func (t *objectSuite) TearDownSuite(c *C) {
	t.store.Close()
}

func (t *objectSuite) TestCreateObject(c *C) {
	if err := t.store.CreateObject(insertObject); err != nil {
		c.Fatal("creating object fails:", errors.ErrorStack(err))
	}
	if insertObject.ID == 0 {
		c.Fatal("expect non zero ID")
	}

	objects := t.store.ListObject()
	if len(objects) != 1 {
		c.Fatalf("expect one element, got %v", objects)
	}
	got := objects[0]

	if !reflect.DeepEqual(insertObject, got) {
		c.Fatalf("expect %v, got %v", *insertObject, *got)
	}
}

func (t *objectSuite) TestUpdateObject(c *C) {
	t.TestCreateObject(c)

	updateObject.ID = insertObject.ID
	updateObject.Ctime = insertObject.Ctime

	if err := t.store.UpdateObject(updateObject); err != nil {
		c.Fatal("updating object fails:", err)
	}
	objects := t.store.ListObject()
	if len(objects) != 1 {
		c.Fatalf("expect one element, got %v", objects)
	}
	got := objects[0]

	if !reflect.DeepEqual(updateObject, got) {
		c.Fatalf("expect %v, got %v", *updateObject, *got)
	}
}

func (t *objectSuite) TestListObject(c *C) {
	t.TestCreateObject(c)

	objects := t.store.ListObject()
	if len(objects) != 1 {
		c.Fatalf("expect one element, got %v", objects)
	}
	got := objects[0]

	if !reflect.DeepEqual(insertObject, got) {
		c.Fatalf("expect %v, got %v", *insertObject, *got)
	}
}

func (t *objectSuite) TestFindObjectByID(c *C) {
	t.TestCreateObject(c)

	got, exists := t.store.GetObject(insertObject.ID)
	c.Assert(exists, Equals, true)
	if !reflect.DeepEqual(insertObject, got) {
		c.Fatalf("expect %v, got %v", *insertObject, *got)
	}
	got, exists = t.store.GetObject(1234567)
	c.Assert(exists, Equals, false)
}

var insertObject = &types.Object{
	ExperimentID: 1,
	BoxID:        1,
	Name:         "bin",
	Payload:      []byte("Hello, world"),
}

var updateObject = &types.Object{
	ExperimentID: 2,
	BoxID:        2,
	Name:         "bin 2",
	Payload:      []byte("Hello, world!"),
}
