import fbe
import proto
from proto import proto
from unittest import TestCase


class TestCreate(TestCase):

    def test_create_and_access(self):
        # Create a new account using FBE model into the FBE stream
        writer = proto.AccountModel(fbe.WriteBuffer())
        self.assertEqual(writer.model.fbe_offset, 4)
        model_begin = writer.create_begin()
        account_begin = writer.model.set_begin()
        writer.model.id.set(1)
        writer.model.name.set("Test")
        writer.model.state.set(proto.State.good)
        wallet_begin = writer.model.wallet.set_begin()
        writer.model.wallet.currency.set("USD")
        writer.model.wallet.amount.set(1000.0)
        writer.model.wallet.set_end(wallet_begin)
        asset_begin = writer.model.asset.set_begin(True)
        asset_wallet_begin = writer.model.asset.value.set_begin()
        writer.model.asset.value.currency.set("EUR")
        writer.model.asset.value.amount.set(100.0)
        writer.model.asset.set_end(asset_begin)
        writer.model.asset.value.set_end(asset_wallet_begin)
        order = writer.model.orders.resize(3)
        order_begin = order.set_begin()
        order.id.set(1)
        order.symbol.set("EURUSD")
        order.side.set(proto.OrderSide.buy)
        order.type.set(proto.OrderType.market)
        order.price.set(1.23456)
        order.volume.set(1000.0)
        order.set_end(order_begin)
        order.fbe_shift(order.fbe_size)
        order_begin = order.set_begin()
        order.id.set(2)
        order.symbol.set("EURUSD")
        order.side.set(proto.OrderSide.sell)
        order.type.set(proto.OrderType.limit)
        order.price.set(1.0)
        order.volume.set(100.0)
        order.set_end(order_begin)
        order.fbe_shift(order.fbe_size)
        order_begin = order.set_begin()
        order.id.set(3)
        order.symbol.set("EURUSD")
        order.side.set(proto.OrderSide.buy)
        order.type.set(proto.OrderType.stop)
        order.price.set(1.5)
        order.volume.set(10.0)
        order.set_end(order_begin)
        order.fbe_shift(order.fbe_size)
        writer.model.set_end(account_begin)
        serialized = writer.create_end(model_begin)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)
        self.assertEqual(writer.model.fbe_offset, (4 + writer.buffer.size))

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 252)

        # Access the account model in the FBE stream
        reader = proto.AccountModel(fbe.ReadBuffer())
        self.assertEqual(reader.model.fbe_offset, 4)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())

        account_begin = reader.model.get_begin()
        id = reader.model.id.get()
        self.assertEqual(id, 1)
        name = reader.model.name.get()
        self.assertEqual(name, "Test")
        state = reader.model.state.get()
        self.assertTrue(state.has_flags(proto.State.good))

        wallet_begin = reader.model.wallet.get_begin()
        wallet_currency = reader.model.wallet.currency.get()
        self.assertEqual(wallet_currency, "USD")
        wallet_amount = reader.model.wallet.amount.get()
        self.assertEqual(wallet_amount, 1000.0)
        reader.model.wallet.get_end(wallet_begin)

        self.assertTrue(reader.model.asset.has_value)
        asset_begin = reader.model.asset.get_begin()
        asset_wallet_begin = reader.model.asset.value.get_begin()
        asset_wallet_currency = reader.model.asset.value.currency.get()
        self.assertEqual(asset_wallet_currency, "EUR")
        asset_wallet_amount = reader.model.asset.value.amount.get()
        self.assertEqual(asset_wallet_amount, 100.0)
        reader.model.asset.value.get_end(asset_wallet_begin)
        reader.model.asset.get_end(asset_begin)

        self.assertEqual(reader.model.orders.size, 3)

        o1 = reader.model.orders[0]
        order_begin = o1.get_begin()
        order_id = o1.id.get()
        self.assertEqual(order_id, 1)
        order_symbol = o1.symbol.get()
        self.assertEqual(order_symbol, "EURUSD")
        order_side = o1.side.get()
        self.assertEqual(order_side, proto.OrderSide.buy)
        order_type = o1.type.get()
        self.assertEqual(order_type, proto.OrderType.market)
        order_price = o1.price.get()
        self.assertEqual(order_price, 1.23456)
        order_volume = o1.volume.get()
        self.assertEqual(order_volume, 1000.0)
        o1.get_end(order_begin)

        o2 = reader.model.orders[1]
        order_begin = o2.get_begin()
        order_id = o2.id.get()
        self.assertEqual(order_id, 2)
        order_symbol = o2.symbol.get()
        self.assertEqual(order_symbol, "EURUSD")
        order_side = o2.side.get()
        self.assertEqual(order_side, proto.OrderSide.sell)
        order_type = o2.type.get()
        self.assertEqual(order_type, proto.OrderType.limit)
        order_price = o2.price.get()
        self.assertEqual(order_price, 1.0)
        order_volume = o2.volume.get()
        self.assertEqual(order_volume, 100.0)
        o1.get_end(order_begin)

        o3 = reader.model.orders[2]
        order_begin = o3.get_begin()
        order_id = o3.id.get()
        self.assertEqual(order_id, 3)
        order_symbol = o3.symbol.get()
        self.assertEqual(order_symbol, "EURUSD")
        order_side = o3.side.get()
        self.assertEqual(order_side, proto.OrderSide.buy)
        order_type = o3.type.get()
        self.assertEqual(order_type, proto.OrderType.stop)
        order_price = o3.price.get()
        self.assertEqual(order_price, 1.5)
        order_volume = o3.volume.get()
        self.assertEqual(order_volume, 10.0)
        o1.get_end(order_begin)

        reader.model.get_end(account_begin)
