///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) typedef int GmbH and contributors.
//  All rights reserved. Licensed under the MIT open-source license.
//
///////////////////////////////////////////////////////////////////////////////

include "wamp.fbs";


namespace demo;


/// Test enumeration A.
enum TestEnumA: uint8
{
    /// Value is unset ("null").
    NONE = 0,

    /// Option A1.
    A1 = 1,

    /// Option A2.
    A2 = 2,
}


/// Test enumeration B.
enum TestEnumB: uint32
{
    /// Value is unset ("null").
    NONE = 0,

    /// Option B1.
    B1 = 1,

    /// Option B1.
    B2 = 2,

    /// Option B1.
    B3 = 1000,

    /// Option B1.
    B4 = 1001,

    /// Option B1.
    B5 = 16777216,

    /// Option B1.
    B6 = 16777217,

    /// Option B1.
    B7 = 4294967295,
}


/// Test struct A
struct TestStructS1
{
    /// Test field 1
    field1: int32;

    /// Test field 2
    field2: uint64;

    /// Test field 3
    field3: uint64 (timestamp, readonly);

    /// Test field 4
    field4: uint160_t (ethadr);
}


/// Test table A with all scalar types, and no attributes.
table TestTableA
{
    /// Test column 1
    column1: bool (arg);

    /// Test column 2
    column2: byte (arg);

    /// Test column 3
    column3: ubyte (arg);

    /// Test column 4
    column4: short (arg);

    /// Test column 5
    column5: ushort (arg);

    /// Test column 6
    column6: int (arg);

    /// Test column 7
    column7: uint (arg);

    /// Test column 8
    column8: long (arg);

    /// Test column 9
    column9: ulong (arg);

    /// Test column 10
    column10: float (arg);

    /// Test column 11
    column11: double (arg);
}


/// Test table B with strings and binaries, with and without attributes.
table TestTableB
{
    /// Test column 1
    column1: string;

    /// Test column 2
    column2: string (wampuri);

    /// Test column 3
    column3: string (url);

    /// Test column 4
    column4: string (multihash);

    /// Test column 5
    column5: [ubyte];

    /// Test column 6
    column6: [uint8];

    /// Test column 7
    column7: [uint8] (cbor);

    /// Test column 8
    column8: [uint8] (ethsig);
}


/// Test table C with integers, with and without attributes.
table TestTableC
{
    /// Test column 1
    column1: uint64;

    /// Test column 2
    column2: uint64 (wampid);

    /// Test column 3
    column3: uint64 (timestamp);
}


/// Test table D
table TestTableD
{
    /// Test column 1
    column1: [uint64] (ndarray);

    /// Test column 2
    column2: [uint32] (ndarray);

    /// Test column 3
    column3: [uint8] (ndarray);

    /// Test column 4
    column4: [double] (ndarray);

    /// Test column 5
    column5: [float] (ndarray);

    /// Test column 6
    column6: [uint64] (wampid, ndarray);

    /// Test column 7
    column7: [uint64] (timestamp, ndarray);
}


/// Test table E
table TestTableE
{
    /// Test column 7
    column18: TestEnumA;

    /// Test column 7
    column19: TestEnumB;

    /// Test column 7
    column17: TestStructS1;
}


/// Test table F
table TestTableF
{
    /// Test column 1
    column1: string (kwarg);

    /// Test column 2
    column2: uint32 (kwarg);

    /// Test column 3
    column3: uint32 (arg);

    /// Test column 4
    column4: uint64 (arg, timestamp);

    /// Test column 5
    column5: string (arg);

    /// Test column 6
    column6: string (arg, wampuri);

    /// Test column 7
    column7: uint160_t (arg, ethadr);

    /// Test column 8
    column8: TestEnumA (arg);

    /// Test column 9
    column9: uint32 (kwarg);

    /// Test column 10
    column10: uint64 (kwarg, timestamp);

    /// Test column 111
    column11: string (kwarg);

    /// Test column 12
    column12: string (kwarg, wampuri);

    /// Test column 13
    column13: uint160_t (kwarg, ethadr);

    /// Test column 14
    column14: TestEnumA (kwarg);

    /// Test column 15
    column15: string (arg);

    /// Test column 16
    column16: uint32 (arg);
}


table TestRequestArgument (type: "request")
{
    /// Test column 1
    column1: string (arg);

    /// Test column 2
    column2: uint32 (arg);

    /// Test column 3
    column3: uint64 (kwarg, timestamp);

    /// Test column 4
    column4: uint160_t (kwarg, ethadr);
}

table TestRequestProgress (type: "progressive-request")
{
    /// Test column 1
    column1: string (arg);

    /// Test column 2
    column2: uint32 (kwarg);
}

table TestResponseResult (type: "result")
{
    /// Test column 1
    column1: string (arg);

    /// Test column 2
    column2: uint32 (arg);

    /// Test column 3
    column3: uint64 (kwarg, timestamp);

    /// Test column 4
    column4: uint160_t (kwarg, ethadr);
}

table TestResponseProgress (type: "progressive-result")
{
    /// Test column 1
    column1: string (arg);

    /// Test column 2
    column2: uint32 (kwarg);
}

table TestResponseError1 (type: "error")
{
    /// Test column 1
    column1: string (arg);

    /// Test column 2
    column2: uint32 (kwarg);
}

table TestResponseError2 (type: "error")
{
    /// Test column 1
    column1: string (arg);

    /// Test column 2
    column2: uint32 (kwarg);
}

union TestRequestAny {
    TestRequestArgument,
    TestRequestProgress,
}

union TestResponseAny {
    TestResponseResult,
    TestResponseProgress,
    TestResponseError1,
    TestResponseError2
}

table TestRequest {
    value: TestRequestAny;
}

table TestResponse {
    value: TestResponseAny;
}


enum ClockMode: uint8
{
    /// Value is unset ("null").
    NONE = 0,

    /// Real-time clock mode.
    REALTIME = 1,

    /// Backtesting clock mode.
    BACKTEST = 2
}


struct ClockTick
{
    address: uint160_t (ethadr);

    mode: ClockMode;

    block: uint256_t (ethblock);

    sweep_no: uint32;

    tick_period: uint32;

    world_period: uint32;

    clock_ts: uint64 (timestamp);

    next_tick: uint32;

    tick_ts: uint64 (timestamp);

    world_ts: uint64 (timestamp);
}


table ClockTickSigned
{
    tick: ClockTick;

    signature: [uint8] (ethsig);
}


/// Interface for signed trading clock.
rpc_service ITradingClock(type: "interface",
                          uuid: "15a72fbf-3800-46ae-8fcd-ae0590e59ead",
                          wampuri: "eth.wamp-proto.demo.clock.<uuid:clock>")
{
    /// Write me.
    get_clock_address (Void): EthAddress (type: "procedure");

    /// Write me.
    on_clock_tick (ClockTickSigned): Void (type: "topic",
                                           wampuri: "on_clock_tick.<int:warp_level>");

    // FIXME: "error: rpc request and response types must be tables"
    // https://github.com/google/flatbuffers/blob/11a19887053534c43f73e74786b46a615ecbf28e/src/idl_parser.cpp#L2658
    //
    // Unions are a good way to be able to send multiple message types as a FlatBuffer.
    // Note that because a union field is really two fields, it must always be part of a
    // table, it cannot be the root of a FlatBuffer by itself.
    // https://google.github.io/flatbuffers/flatbuffers_guide_writing_schema.html

    run_test (TestRequest): TestResponse (type: "procedure");
}
