///@system  Dstar V10 api demo
///@file    main.cpp
///@author  Hao Lin 2021-01-20

#include <stdio.h>
#if defined WIN32 || defined _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

#include "ApiClient.h"
#include "UdpClient.h"

char    front_ip[] = "101.132.153.16";

int     front_port = 6668;                  
int     udp_port = 6666;                    //udp报单端口

char    account[] = "V106020";
char    passwd[] = "123456";
char    new_passwd[] = "123456@deadbeef";
char    app_id[] = "esunny_epolestar_9.0";
char    license_no[] = "esunny_epolestar";

int     contindex = 0;
char    contractno[] = "CF903";
int     option_contindex = 24;
char    option_contractno[] = "CF001C14600";
char    direct = DSTAR_API_DIRECT_BUY;
char    offset = DSTAR_API_OFFSET_OPEN;
int     qty = 1;
int     min_qty = 0;
double  price = 15000;
int     client_reqid = 1;
int     reference = 1;
int     cmb_contindex1 = 374;
char    cmb_contractno1[] = "SR903C5600";
int     cmb_contindex2 = 400;
char    cmb_contractno2[] = "SR903P5600";
double  cmb_price = 1200;

unsigned int udp_or_tcp = 0; // 0 udp 1 tcp 

TUdpClient g_UdpClient;
ApiClient g_ApiClient;

void UdpAuth();
void FillHead(DstarApiHead *head, DstarApiProtocolCodeType protocol, int framesize);
void InsertOrder();
void InsertBatchOrder();
void InsertEnquiry();
void InsertOffer(char *enquiryno);
void InsertBatchOffer();
void InsertOptionExec();
void InsertCmbOrder();
int UdpOrderTest();


void TcpInsertOrder();
void TcpInsertEnquiry();
void TcpInsertOffer(char *enquiryno);
void TcpInsertOptionExec();
void TcpInsertCmbOrder();
void TcpDeleteOrder(DstarApiOrderIdType orderid, char *sysno);
int TcpOrderTest();

void TSleep(int sec);

void PwdMod();

int main(int argc, char *argv[])
{
    if(0 == udp_or_tcp)
    {
        UdpOrderTest();
    }
    else if(1 == udp_or_tcp)
    {
        TcpOrderTest();
    }

    while(1)
    {
        TSleep(15);
    }

    return 0;
}

void FillHead(DstarApiHead *head, DstarApiProtocolCodeType protocol, int nLen)
{
    head->ProtocolCode = protocol;
    head->DataLen = nLen;
}

//认证
void UdpAuth()
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqUdpAuthField *req = (DstarApiReqUdpAuthField *)&sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_UdpAuth, sizeof(DstarApiReqUdpAuthField));
    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ReqIdMode = DSTAR_API_REQIDMODE_NOCHECK;
    g_UdpClient.Send(sendbuf, sizeof(DstarApiReqUdpAuthField) + sizeof(DstarApiHead));
}

//报单
void InsertOrder()
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqOrderInsertField *req = (DstarApiReqOrderInsertField *)&sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_OrderInsert, sizeof(DstarApiReqOrderInsertField));
    req->Direct = direct;
    req->Offset = offset;
    req->Hedge = DSTAR_API_HEDGE_SPECULATE;
    req->OrderType = DSTAR_API_ORDERTYPE_LIMIT;
    req->ValidType = DSTAR_API_VALID_GFD;
    req->Reference = reference++;
    req->SeatIndex = 1;
    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ClientReqId = client_reqid++;
    req->ContractIndex = contindex;
    strncpy(req->ContractNo, contractno, sizeof(DstarApiContractNoType) - 1);
    req->OrderQty = qty;
    req->OrderPrice = price;
    req->MinQty = min_qty;
    
    g_UdpClient.Send(sendbuf, sizeof(DstarApiReqOrderInsertField) + sizeof(DstarApiHead));
}

//批量报单
void InsertBatchOrder() 
{
    char sendbuf[1024] = {0};
    int batch_num = 6;
    DstarApiReqOrderInsertField *req = NULL;
    DstarApiHead *head = NULL;
    int pos = 0;
    for (int i = 0; i < batch_num; ++i) {
        head = (DstarApiHead *)&sendbuf[pos];
        req = (DstarApiReqOrderInsertField *) & sendbuf[pos + sizeof(DstarApiHead)];
        FillHead(head, CMD_API_Req_OrderInsert, sizeof (DstarApiReqOrderInsertField));
        req->Direct = direct;
        req->Offset = offset;
        req->Hedge = DSTAR_API_HEDGE_SPECULATE;
        req->OrderType = DSTAR_API_ORDERTYPE_LIMIT;
        req->ValidType = DSTAR_API_VALID_GFD;
        req->Reference = reference++;
        req->SeatIndex = 1;
        req->AccountIndex = g_ApiClient.GetAccountIndex();
        req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
        req->ClientReqId = client_reqid++;
        req->ContractIndex = contindex;
        strncpy(req->ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
        req->OrderQty = qty;
        req->OrderPrice = price;
        req->MinQty = min_qty;
        pos += (sizeof(DstarApiHead) + sizeof(DstarApiReqOrderInsertField));
    }

    g_UdpClient.Send(sendbuf, pos);
}

//询价
void InsertEnquiry() 
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqOrderInsertField *req = (DstarApiReqOrderInsertField *) &sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_OrderInsert, sizeof (DstarApiReqOrderInsertField));
    req->Direct = DSTAR_API_DIRECT_ALL;
    req->OrderType = DSTAR_API_ORDERTYPE_ENQUIRY;
    req->Reference = reference++;
    req->SeatIndex = 1;
    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ClientReqId = client_reqid++;
    req->ContractIndex = contindex;
    strncpy(req->ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
    g_UdpClient.Send(sendbuf, sizeof (DstarApiReqOrderInsertField) + sizeof(DstarApiHead));
}

//行权
void InsertOptionExec() 
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqOrderInsertField *req = (DstarApiReqOrderInsertField *) &sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_OrderInsert, sizeof (DstarApiReqOrderInsertField));
    req->OrderType = DSTAR_API_ORDERTYPE_EXECUTE;
    req->Reference = reference++;
    req->SeatIndex = 1;
    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ClientReqId = client_reqid++;
    req->ContractIndex = option_contindex;
    strncpy(req->ContractNo, option_contractno, sizeof (DstarApiContractNoType) - 1);
    req->OrderQty = qty;
    g_UdpClient.Send(sendbuf, sizeof (DstarApiReqOrderInsertField) + sizeof(DstarApiHead));
}

//报价
void InsertOffer(char *enquiryno) 
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqOfferInsertField *req = (DstarApiReqOfferInsertField *) &sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_OfferInsert, sizeof (DstarApiReqOfferInsertField));
    req->BuyOffset = offset;
    req->SellOffset = offset;
    req->SeatIndex = 1;
    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ClientReqId = client_reqid++;
    req->ContractIndex = contindex;
    strncpy(req->ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
    req->OrderQty = qty;
    req->BuyPrice = price;
    req->SellPrice = price;
    req->Reference = reference++;
    //询价号
    if (enquiryno != NULL && strlen(enquiryno) > 0) {
        strncpy(req->EnquiryNo, enquiryno, sizeof (DstarApiSystemNoType) - 1);
    }

    g_UdpClient.Send(sendbuf, sizeof (DstarApiReqOfferInsertField) + sizeof(DstarApiHead));
}

//新报价
void InsertOfferNew(char *enquiryno) 
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqOfferInsertNewField *req = (DstarApiReqOfferInsertNewField *) &sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_OfferInsertNew, sizeof (DstarApiReqOfferInsertNewField));
    req->BuyOffset = offset;
    req->SellOffset = offset;
    req->SeatIndex = 1;
    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ClientReqId = client_reqid++;
    req->ContractIndex = contindex;
    strncpy(req->ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
    req->BuyOrderQty = qty;
    req->SellOrderQty = qty;
    req->BuyPrice = price;
    req->SellPrice = price;
    req->Reference = reference++;
    // req->ReplaceId = DSTAR_API_REPLACE_NORMAL;
    // req->ReplaceId = DSTAR_API_REPLACE_LAST;
    //询价号
    if (enquiryno != NULL && strlen(enquiryno) > 0) {
        strncpy(req->EnquiryNo, enquiryno, sizeof (DstarApiSystemNoType) - 1);
    }

    g_UdpClient.Send(sendbuf, sizeof (DstarApiReqOfferInsertNewField) + sizeof(DstarApiHead));
}

//批量报价单
void InsertBatchOffer() 
{
    char sendbuf[1024] = {0};
    int batch_num = 6;
    DstarApiHead *head = NULL;
    DstarApiReqOfferInsertField *req = NULL;
    int pos = 0;
    for (int i = 0; i < batch_num; ++i) {
        head = (DstarApiHead *)&sendbuf[pos];
        req = (DstarApiReqOfferInsertField *) & sendbuf[pos + sizeof(DstarApiHead)];
        FillHead(head, CMD_API_Req_OfferInsert, sizeof(DstarApiReqOfferInsertField));
        req->BuyOffset = offset;
        req->SellOffset = offset;
        req->SeatIndex = 1;
        req->AccountIndex = g_ApiClient.GetAccountIndex();
        req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
        req->ClientReqId = client_reqid++;
        req->ContractIndex = contindex;
        strncpy(req->ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
        req->OrderQty = qty;
        req->BuyPrice = price;
        req->SellPrice = price;
        req->Reference = reference++;
        pos += sizeof(DstarApiReqOfferInsertField) + sizeof(DstarApiHead);
    }

    g_UdpClient.Send(sendbuf, pos);
}

void DeleteOrder(DstarApiOrderIdType orderid, char *sysno) 
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqOrderDeleteField *req = (DstarApiReqOrderDeleteField *) &sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_OrderDelete, sizeof (DstarApiReqOrderDeleteField));

    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ClientReqId = client_reqid++;
    req->Reference = reference++;
    req->SeatIndex = 0;
    req->OrderId = orderid;
    //系统号
    if (sysno != NULL && strlen(sysno) > 0) {
        strncpy(req->SystemNo, sysno, sizeof (DstarApiSystemNoType) - 1);
    }
    g_UdpClient.Send(sendbuf, sizeof (DstarApiReqOrderDeleteField) + sizeof (DstarApiHead));
}

//组合报单
void InsertCmbOrder()
{
    char sendbuf[1024] = {0};
    DstarApiHead *head = (DstarApiHead*)sendbuf;
    DstarApiReqCmbOrderInsertField *req = (DstarApiReqCmbOrderInsertField *)&sendbuf[sizeof(DstarApiHead)];
    FillHead(head, CMD_API_Req_CmbOrderInsert, sizeof(DstarApiReqCmbOrderInsertField));
    req->Direct = direct;
    req->Offset = offset;
    req->Hedge = DSTAR_API_HEDGE_SPECULATE;
    req->OrderType = DSTAR_API_ORDERTYPE_LIMIT;
    req->ValidType = DSTAR_API_VALID_IOC;
    req->Reference = reference++;
    req->SeatIndex = 1;
    req->AccountIndex = g_ApiClient.GetAccountIndex();
    req->UdpAuthCode = g_ApiClient.GetUdpAuthCode();
    req->ClientReqId = client_reqid++;
    req->ContractIndex1 = cmb_contindex1;
    strncpy(req->ContractNo1, cmb_contractno1, sizeof(DstarApiContractNoType) - 1);
    req->ContractIndex2 = cmb_contindex2;
    strncpy(req->ContractNo2, cmb_contractno2, sizeof(DstarApiContractNoType) - 1);
    req->OrderQty = qty;
    req->OrderPrice = cmb_price;
    req->MinQty = min_qty;
    
    g_UdpClient.Send(sendbuf, sizeof(DstarApiReqCmbOrderInsertField) + sizeof(DstarApiHead));
}

int UdpOrderTest()
{
    //创建API
    if (g_ApiClient.CreateApi() != 0 )
    {
        return 1;
    }
    
    //UDP初始化
    if (g_UdpClient.Init(front_ip, udp_port) != 0)
    {
        printf("udp client init failed\n");
        return 1;
    }
    
    //设置信息
    g_ApiClient.SetAddress(front_ip, front_port);
    g_ApiClient.SetUser(account, passwd, app_id, license_no);
    
    //初始化
    int ret = g_ApiClient.Init();
    if(ret < 0)
    {
        printf("Api init failed, ret=%d\n", ret);
        return 1;
    }

    //等待API初始化就绪
    while (!g_ApiClient.IsReady())
    {
        if(g_ApiClient.IsForcePwdMod())
            PwdMod();
        TSleep(1);
    }

    //UDP认证
    UdpAuth();

    //等待认证就绪
    while (!g_ApiClient.IsUdpAuth())
    {
        TSleep(1);
    }
    
    //报单
    InsertOrder();

    printf("Stage1\n");
    
    TSleep(10);
    
    //批量报单
    InsertBatchOrder();

    printf("Stage2\n");
    
    TSleep(10);
    
    //询价
    InsertEnquiry();

    printf("Stage3\n");
    
    TSleep(10);
    
    //报价
    InsertOffer(0);

    printf("Stage4\n");
    
    TSleep(10);
    
    //批量报价
    InsertBatchOffer();

    printf("Stage5\n");
    
    //行权
    InsertOptionExec();

    printf("Stage6\n");
    
    // 组合报单
    InsertCmbOrder();
    printf("Stage7\n");

    // 新报价
    InsertOfferNew(0);
    printf("Stage8\n");
    
    return 0;
}

void TcpInsertOrder()
{
    DstarApiReqOrderInsertField req = { 0 };
    req.Direct = direct;
    req.Offset = offset;
    req.Hedge = DSTAR_API_HEDGE_SPECULATE;
    req.OrderType = DSTAR_API_ORDERTYPE_LIMIT;
    req.ValidType = DSTAR_API_VALID_GFD;
    req.Reference = reference++;
    req.SeatIndex = 1;
    req.AccountIndex = g_ApiClient.GetAccountIndex();
    // req.UdpAuthCode =  !!! TCP报单无需填写
    req.ClientReqId = client_reqid++;
    req.ContractIndex = 33;
    strncpy(req.ContractNo, contractno, sizeof(DstarApiContractNoType) - 1);
    req.OrderQty = qty;
    req.OrderPrice = price;
    req.MinQty = min_qty;
    
    g_ApiClient.ReqOrderInsert(&req);

}

void TcpInsertEnquiry()
{
    DstarApiReqOrderInsertField req = { 0 };
    req.Direct = DSTAR_API_DIRECT_ALL;
    req.OrderType = DSTAR_API_ORDERTYPE_ENQUIRY;
    req.Reference = reference++;
    req.SeatIndex = 1;
    req.AccountIndex = g_ApiClient.GetAccountIndex();
    // req.UdpAuthCode =  !!! TCP报单无需填写
    req.ClientReqId = client_reqid++;
    req.ContractIndex = contindex;
    strncpy(req.ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
    
    g_ApiClient.ReqOrderInsert(&req);
}

void TcpInsertOffer(char *enquiryno)
{
    DstarApiReqOfferInsertField req = { 0 };
    req.BuyOffset = offset;
    req.SellOffset = offset;
    req.SeatIndex = 1;
    req.AccountIndex = g_ApiClient.GetAccountIndex();
    // req.UdpAuthCode =  !!! TCP报单无需填写
    req.ClientReqId = client_reqid++;
    req.ContractIndex = contindex;
    strncpy(req.ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
    req.OrderQty = qty;
    req.BuyPrice = 14900;
    req.SellPrice = 15100;
    req.Reference = reference++;
    //询价号
    if (enquiryno != NULL && strlen(enquiryno) > 0) {
        strncpy(req.EnquiryNo, enquiryno, sizeof (DstarApiSystemNoType) - 1);
    }

    g_ApiClient.ReqOfferInsert(&req);
}

void TcpInsertOfferNew(char *enquiryno)
{
    DstarApiReqOfferInsertNewField req = { 0 };
    req.BuyOffset = offset;
    req.SellOffset = offset;
    req.SeatIndex = 1;
    req.AccountIndex = g_ApiClient.GetAccountIndex();
    // req.UdpAuthCode =  !!! TCP报单无需填写
    req.ClientReqId = client_reqid++;
    req.ContractIndex = contindex;
    strncpy(req.ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
    req.BuyOrderQty = qty;
    req.SellOrderQty = qty;
    req.BuyPrice = 14900;
    req.SellPrice = 15100;
    req.Reference = reference++;
    // req.ReplaceId = DSTAR_API_REPLACE_NORMAL;
    // req.ReplaceId = DSTAR_API_REPLACE_LAST;
    //询价号
    if (enquiryno != NULL && strlen(enquiryno) > 0) {
        strncpy(req.EnquiryNo, enquiryno, sizeof (DstarApiSystemNoType) - 1);
    }

    g_ApiClient.ReqOfferInsertNew(&req);
}

void TcpInsertOptionExec()
{
    DstarApiReqOrderInsertField req = { 0 };
    req.OrderType = DSTAR_API_ORDERTYPE_ABANDON;
    req.Reference = reference++;
    req.SeatIndex = 1;
    req.AccountIndex = g_ApiClient.GetAccountIndex();
    // req.UdpAuthCode =  !!! TCP报单无需填写
    req.ClientReqId = client_reqid++;
    req.ContractIndex = contindex;
    strncpy(req.ContractNo, contractno, sizeof (DstarApiContractNoType) - 1);
    req.OrderQty = 1;
    g_ApiClient.ReqOrderInsert(&req);
    
}

void TcpInsertCmbOrder()
{
    DstarApiReqCmbOrderInsertField req = { 0 };
    req.Direct = direct;
    req.Offset = offset;
    req.Hedge = DSTAR_API_HEDGE_SPECULATE;
    req.OrderType = DSTAR_API_ORDERTYPE_LIMIT;
    req.ValidType = DSTAR_API_VALID_IOC;
    req.Reference = reference++;
    req.SeatIndex = 1;
    req.AccountIndex = g_ApiClient.GetAccountIndex();
    // req.UdpAuthCode =  !!! TCP报单无需填写
    req.ClientReqId = client_reqid++;
    req.ContractIndex1 = cmb_contindex1;
    strncpy(req.ContractNo1, cmb_contractno1, sizeof(DstarApiContractNoType) - 1);
    req.ContractIndex2 = cmb_contindex2;
    strncpy(req.ContractNo2, cmb_contractno2, sizeof(DstarApiContractNoType) - 1);
    req.OrderQty = qty;
    req.OrderPrice = cmb_price;
    req.MinQty = min_qty;
    g_ApiClient.ReqCmbOrderInsert(&req);
}

void TcpDeleteOrder(DstarApiOrderIdType orderid, char *sysno)
{
    DstarApiReqOrderDeleteField req = { 0 };
    req.AccountIndex = g_ApiClient.GetAccountIndex();
    // req.UdpAuthCode =  !!! TCP报单无需填写
    req.ClientReqId = client_reqid++;
    req.Reference = reference++;
    req.SeatIndex = 0;
    req.OrderId = orderid;
    //系统号
    if (sysno != NULL && strlen(sysno) > 0)
    {
        strncpy(req.SystemNo, sysno, sizeof (DstarApiSystemNoType) - 1);
    }
    g_ApiClient.ReqOrderDelete(&req);
}

int TcpOrderTest()
{
    //创建API
    if (g_ApiClient.CreateApi() != 0 )
    {
        return 1;
    }
    
    //设置信息
    g_ApiClient.SetAddress(front_ip, front_port);
    g_ApiClient.SetUser(account, passwd, app_id, license_no);
    
    //初始化
    int ret = g_ApiClient.Init();
    if(ret < 0)
    {
        printf("Api init failed, ret=%d\n", ret);
        return 1;
    }

    //等待API初始化就绪
    while (!g_ApiClient.IsReady())
    {
        if(g_ApiClient.IsForcePwdMod())
            PwdMod();
        TSleep(1);
    }
    
    printf("Api ready\n");
    
    //报单
    TcpInsertOrder();

    printf("Stage1\n");
    
    TSleep(10);
    
    //询价
    TcpInsertEnquiry();

    printf("Stage2\n");
    
    TSleep(10);
    
    //报价
    TcpInsertOffer(0);

    printf("Stage3\n");
    
    TSleep(10);
    
    //行权
    TcpInsertOptionExec();

    printf("Stage4\n");

    TSleep(10);
    
    // 组合报单
    TcpInsertCmbOrder();

    printf("Stage5\n");

    TSleep(10);

    // 新报价
    TcpInsertOfferNew(0);

    printf("Stage6\n");
    
    TSleep(10);
    
    // 撤单
    // TcpDeleteOrder(2019012100000000031, NULL);


    while(1)
    {
        TSleep(5);
    }
    return 0;
}

void TSleep(int sec)
{
#if defined WIN32 || defined _WIN32
    Sleep(1000 * sec);
#else
    sleep(sec);
#endif
}

void PwdMod()
{
    g_ApiClient.PwdMod(new_passwd);
}
