package tests

import "testing"
import "github.com/stretchr/testify/assert"
import "../proto/fbe"
import "../proto/proto"

func TestCreate(t *testing.T) {
	// Create a new account using FBE model into the FBE stream
	writer := proto.NewAccountModel(fbe.NewEmptyBuffer())
	assert.EqualValues(t, writer.Model().FBEOffset(), 4)
	modelBegin := writer.CreateBegin()
	accountBegin, _ := writer.Model().SetBegin()
	_ = writer.Model().Id.Set(1)
	_ = writer.Model().Name.Set("Test")
	_ = writer.Model().State.SetValue(proto.State_good)
	walletBegin, _ := writer.Model().Wallet.SetBegin()
	_ = writer.Model().Wallet.Currency.Set("USD")
	_ = writer.Model().Wallet.Amount.Set(1000.0)
	writer.Model().Wallet.SetEnd(walletBegin)
	assetBegin, _ := writer.Model().Asset.SetBegin(true)
	assetWalletBegin, _ := writer.Model().Asset.Value().SetBegin()
	_ = writer.Model().Asset.Value().Currency.Set("EUR")
	_ = writer.Model().Asset.Value().Amount.Set(100.0)
	writer.Model().Asset.SetEnd(assetBegin)
	writer.Model().Asset.Value().SetEnd(assetWalletBegin)
	order, _ := writer.Model().Orders.Resize(3)
	orderBegin, _ := order.SetBegin()
	_ = order.Id.Set(1)
	_ = order.Symbol.Set("EURUSD")
	_ = order.Side.SetValue(proto.OrderSide_buy)
	_ = order.Type.SetValue(proto.OrderType_market)
	_ = order.Price.Set(1.23456)
	_ = order.Volume.Set(1000.0)
	order.SetEnd(orderBegin)
	order.FBEShift(order.FBESize())
	orderBegin, _ = order.SetBegin()
	_ = order.Id.Set(2)
	_ = order.Symbol.Set("EURUSD")
	_ = order.Side.SetValue(proto.OrderSide_sell)
	_ = order.Type.SetValue(proto.OrderType_limit)
	_ = order.Price.Set(1.0)
	_ = order.Volume.Set(100.0)
	order.SetEnd(orderBegin)
	order.FBEShift(order.FBESize())
	orderBegin, _ = order.SetBegin()
	_ = order.Id.Set(3)
	_ = order.Symbol.Set("EURUSD")
	_ = order.Side.SetValue(proto.OrderSide_buy)
	_ = order.Type.SetValue(proto.OrderType_stop)
	_ = order.Price.Set(1.5)
	_ = order.Volume.Set(10.0)
	order.SetEnd(orderBegin)
	order.FBEShift(order.FBESize())
	writer.Model().SetEnd(accountBegin)
	serialized := writer.CreateEnd(modelBegin)
	assert.EqualValues(t, serialized, writer.Buffer().Size())
	assert.True(t, writer.Verify())
	writer.Next(serialized)
	assert.EqualValues(t, writer.Model().FBEOffset(), 4+writer.Buffer().Size())

	// Check the serialized FBE size
	assert.EqualValues(t, writer.Buffer().Size(), 252)

	// Access the account model in the FBE stream
	reader := proto.NewAccountModel(writer.Buffer())
	assert.EqualValues(t, reader.Model().FBEOffset(), 4)
	assert.True(t, reader.Verify())

	accountBegin, _ = reader.Model().GetBegin()
	id, _ := reader.Model().Id.Get()
	assert.EqualValues(t, id, 1)
	name, _ := reader.Model().Name.Get()
	assert.EqualValues(t, name, "Test")
	state, _ := reader.Model().State.Get()
	assert.True(t, state.HasFlags(proto.State_good))

	walletBegin, _ = reader.Model().Wallet.GetBegin()
	walletCurrency, _ := reader.Model().Wallet.Currency.Get()
	assert.EqualValues(t, walletCurrency, "USD")
	walletAmount, _ := reader.Model().Wallet.Amount.Get()
	assert.EqualValues(t, walletAmount, 1000.0)
	reader.Model().Wallet.GetEnd(walletBegin)

	assert.True(t, reader.Model().Asset.HasValue())
	assetBegin, _ = reader.Model().Asset.GetBegin()
	assetWalletBegin, _ = reader.Model().Asset.Value().GetBegin()
	assetWalletCurrency, _ := reader.Model().Asset.Value().Currency.Get()
	assert.EqualValues(t, assetWalletCurrency, "EUR")
	assetWalletAmount, _ := reader.Model().Asset.Value().Amount.Get()
	assert.EqualValues(t, assetWalletAmount, 100.0)
	reader.Model().Asset.Value().GetEnd(assetWalletBegin)
	reader.Model().Asset.GetEnd(assetBegin)

	assert.EqualValues(t, reader.Model().Orders.Size(), 3)

	o1, _ := reader.Model().Orders.GetItem(0)
	orderBegin, _ = o1.GetBegin()
	orderId, _ := o1.Id.Get()
	assert.EqualValues(t, orderId, 1)
	orderSymbol, _ := o1.Symbol.Get()
	assert.EqualValues(t, orderSymbol, "EURUSD")
	orderSide, _ := o1.Side.Get()
	assert.EqualValues(t, *orderSide, proto.OrderSide_buy)
	orderType, _ := o1.Type.Get()
	assert.EqualValues(t, *orderType, proto.OrderType_market)
	orderPrice, _ := o1.Price.Get()
	assert.EqualValues(t, orderPrice, 1.23456)
	orderVolume, _ := o1.Volume.Get()
	assert.EqualValues(t, orderVolume, 1000.0)
	o1.GetEnd(orderBegin)

	o2, _ := reader.Model().Orders.GetItem(1)
	orderBegin, _ = o2.GetBegin()
	orderId, _ = o2.Id.Get()
	assert.EqualValues(t, orderId, 2)
	orderSymbol, _ = o2.Symbol.Get()
	assert.EqualValues(t, orderSymbol, "EURUSD")
	orderSide, _ = o2.Side.Get()
	assert.EqualValues(t, *orderSide, proto.OrderSide_sell)
	orderType, _ = o2.Type.Get()
	assert.EqualValues(t, *orderType, proto.OrderType_limit)
	orderPrice, _ = o2.Price.Get()
	assert.EqualValues(t, orderPrice, 1.0)
	orderVolume, _ = o2.Volume.Get()
	assert.EqualValues(t, orderVolume, 100.0)
	o2.GetEnd(orderBegin)

	o3, _ := reader.Model().Orders.GetItem(2)
	orderBegin, _ = o3.GetBegin()
	orderId, _ = o3.Id.Get()
	assert.EqualValues(t, orderId, 3)
	orderSymbol, _ = o3.Symbol.Get()
	assert.EqualValues(t, orderSymbol, "EURUSD")
	orderSide, _ = o3.Side.Get()
	assert.EqualValues(t, *orderSide, proto.OrderSide_buy)
	orderType, _ = o3.Type.Get()
	assert.EqualValues(t, *orderType, proto.OrderType_stop)
	orderPrice, _ = o3.Price.Get()
	assert.EqualValues(t, orderPrice, 1.5)
	orderVolume, _ = o3.Volume.Get()
	assert.EqualValues(t, orderVolume, 10.0)
	o3.GetEnd(orderBegin)

	reader.Model().GetEnd(accountBegin)
}
