#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <unistd.h>
#include <assert.h>
#include <map>
#include <sstream>
#include "XeleSecuritiesTraderApi.h"

using namespace std;
using std::max;
using std::min;

#define INFOPRINT(fmt, ...) printf(fmt,  ##__VA_ARGS__); printf("\n");

#define PRINT_RSP(RSPINFO, nRequestID, bIsLast)  \
fprintf(stdout, "{%s} Pass ErrorID:%d, ErrorMsg:%s nRequestID:%d bIsLast:%d\n", __FUNCTION__, \
         RSPINFO->ErrorID, RSPINFO->ErrorMsg, nRequestID, bIsLast)

#define PRINT_RSP_ERR(RSPINFO, nRequestID, bIsLast)  \
fprintf(stdout, "{%s} Fail ErrorID:%d, ErrorMsg:%s nRequestID:%d bIsLast:%d\n", __FUNCTION__, \
         RSPINFO->ErrorID, RSPINFO->ErrorMsg, nRequestID, bIsLast)

class DemoTrader : public XeleSecuritiesTraderSpi {
 public:
  explicit DemoTrader(XeleSecuritiesTraderApi *api);
  ~DemoTrader();

 public:
  void readConfig();
  void resetEventFlag(bool flag);
  void waitRspEvent();

  int reqLogin();
  void reqOrder(char side);
  void reqCancelOrder();
  void reqCombOrder(char side);
  void reqQryOrder();
  void reqLogout();

 public:
  void onApiMsg(int ret, const char *strFormat, ...) override;

  void onFrontManagerQueryDisconnected(int nReason) override;
  void onFrontQueryDisconnected(int nReason) override;
  void onFrontTradeDisconnected(int nReason) override;

  void onRspLogin(CXeleRspUserLoginField *pRspField, CXeleRspInfo *pRspInfo,
                  int nRequestID, bool bIsLast) override;
  void onRspInitTrader(CXeleRspInitTraderField *pRspField, CXeleRspInfo *pRspInfo,
                       int nRequestID, bool bIsLast) override;
  void onRspLogout(CXeleRspUserLogoutField *pRspField, CXeleRspInfo *pRspInfo,
                   int nRequestID, bool bIsLast) override;

  void onRspInsertOrder(CXeleRspOrderInsertField *pRspField, CXeleRspInfo *pRspInfo,
                        int nRequestID, bool bIsLast) override;
  void onRspCancelOrder(CXeleRspOrderActionField *pRspField, CXeleRspInfo *pRspInfo,
                        int nRequestID, bool bIsLast) override;
  void onRtnOrder(CXeleRtnOrderField *pRspField, CXeleRspInfo *pRspInfo,
                  int nRequestID, bool bIsLast) override;
  void onRtnTrade(CXeleRtnTradeField *pRspField, CXeleRspInfo *pRspInfo,
                  int nRequestID, bool bIsLast) override;
  void onErrRtnInsertOrder(CXeleRspOrderInsertField *pRspField, CXeleRspInfo *pRspInfo,
                           int nRequestID, bool bIsLast) override;
  void onErrRtnCancelOrder(CXeleRspOrderActionField *pRspField, CXeleRspInfo *pRspInfo,
                           int nRequestID, bool bIsLast) override;

  void onRspInsertCombOrder(CXeleRspOptionCombInsertField *pRspField, CXeleRspInfo *pRspInfo,
                            int nRequestID, bool bIsLast) override;
  void onRtnCombOrder(CXeleRtnOptionCombOrderField *pRspField, CXeleRspInfo *pRspInfo,
                      int nRequestID, bool bIsLast) override;
  void onRtnCombTrade(CXeleRtnOptionCombTradeField *pRspField, CXeleRspInfo *pRspInfo,
                      int nRequestID, bool bIsLast) override;
  void onErrRtnInsertCombOrder(CXeleRspOptionCombInsertField *pRspField, CXeleRspInfo *pRspInfo,
                               int nRequestID, bool bIsLast) override;

  void onRspQryOrder(CXeleRspQryOrderField *pRspField, CXeleRspInfo *pRspInfo,
                     int nRequestID, bool bIsLast) override;
  void onRspQryTrade(CXeleRspQryTradeField *pRspField, CXeleRspInfo *pRspInfo,
                     int nRequestID, bool bIsLast) override;

 private:
  bool m_rspEvent;
  unsigned int m_maxLocalID;        ///< 用户本地报单ID，递增填充OrderID
  unsigned int m_maxOriginOrderID;  ///< 报单柜台ID，Rsp返回后获取，用于查询和撤单，柜台仅支持柜台ID撤单
  char m_splitOrderID[sizeof(TXeleSecondaryOrderType) + 1];
  XeleSecuritiesTraderApi *m_userApi;

  CXeleReqOrderInsertField m_reqOrderPkt;
  CXeleReqOptionCombInsertField m_reqComOrderPkt;

  int m_requestID;
  std::map<string, string> m_config;
};