/**
 * Copyright 2022 ACCELECOM LTD.  All Rights Reserved.
 *  @company 南京艾科朗克信息科技有限公司
 *  @author fengyul
 *  @modify fengyul
 *  @source encoding UTF-8
 *  @console encoding GB2312
 *  @Formatter GNU Built-in
 *  @brief 一个简单的例子，介绍XeleSecuritiesTraderApi和XeleSecuritiesTraderSpi接口的使用。
 *	登陆、报撤单、组合保证金报单及查询报单的功能演示
 */

#include <demo_trader.h>

DemoTrader::DemoTrader(XeleSecuritiesTraderApi *api) {
  m_rspEvent = false;
  m_maxLocalID = 0;
  m_maxOriginOrderID = 0;
  m_requestID = 0;
  memset(m_splitOrderID, 0, sizeof(m_splitOrderID));
  m_userApi = api;
  m_config.clear();

  readConfig();  ///< 读取demo配置
}

DemoTrader::~DemoTrader() {}

/**
 * 读取配置
 */
void DemoTrader::readConfig() {
  m_config.clear();
  ifstream fin("./demo_config.ini");
  if (!fin) {
    INFOPRINT("config file not exist");
    exit(0);
  }
  string s;
  char key[100];
  char value[100];
  while (getline(fin, s)) {
    if (0 == strncmp(s.c_str(), "#", 1))
      continue;
    memset(key, 0, 100);
    memset(value, 0, 100);
    sscanf(s.c_str(), "%[^=]=%s", key, value);
    m_config[key] = value;
  }
}

void DemoTrader::resetEventFlag(bool flag) {
  m_rspEvent = flag;
}

/**
 * 等待响应事件
 */
void DemoTrader::waitRspEvent() {
  size_t count = 0;
  do {
    usleep(500000);
    count++;
  } while (true != m_rspEvent && count < 10);
  if (count >= 10) {
    INFOPRINT("wait rsp event timeout! maybe something error");
  }
}

/**
 * 登陆请求
 */
int DemoTrader::reqLogin() {
  INFOPRINT("---------------------------LOGIN  BEGIN---------------------------");
  resetEventFlag(false);
  int ret = m_userApi->reqLogin("./api_config.txt",
                                m_config["AccountID"].c_str(),
                                m_config["OldPassword"].c_str(),
                                atoi(m_config["SubClientIndex"].c_str()),
                                m_config["Market"].c_str()[0],
                                DemoTrader::m_requestID++);
  if (ret) {
    INFOPRINT("login failed, ret[%d]", ret);
    return -1;
  }
  waitRspEvent();
  INFOPRINT("---------------------------LOGIN  END---------------------------\n");
  return 0;
}

/**
 * 登出请求
 */
void DemoTrader::reqLogout() {
  INFOPRINT("---------------------------LOGOUT BEGIN---------------------------");
  resetEventFlag(false);
  m_userApi->reqLogout(m_config["AccountID"].c_str(), m_requestID++);
  waitRspEvent();
  INFOPRINT("---------------------------LOGOUT END---------------------------\n");
}

/**
 * 报单请求
 */
void DemoTrader::reqOrder(char side) {
  INFOPRINT("--------------------------ORDER  BEGIN--------------------------");
  resetEventFlag(false);
  memset(&m_reqOrderPkt, 0, sizeof(CXeleReqOrderInsertField));
  m_reqOrderPkt.UserLocalID = m_maxLocalID++;
  strncpy(m_reqOrderPkt.SecuritiesID, m_config["SecuritiesID"].c_str(), sizeof(m_reqOrderPkt.SecuritiesID));
  m_reqOrderPkt.Direction = side;
  m_reqOrderPkt.LimitPrice = atof(m_config["LimitPrice"].c_str());
  m_reqOrderPkt.Volume = atoi(m_config["Volume"].c_str());
  m_reqOrderPkt.OrderType = XELE_LIMIT_PRICE_TYPE;
  m_reqOrderPkt.CmbOffsetFlag = XELE_COMBOFFSET_FLAG_OPEN;
  m_reqOrderPkt.TimeCondition = XELE_TIMEINFORCE_TYPE_GFD;
  m_reqOrderPkt.Operway = API_OPERWAY;

  m_userApi->reqInsertOrder(m_reqOrderPkt, m_requestID++);

  waitRspEvent();
  INFOPRINT("---------------------------ORDER  END---------------------------\n");
}

/**
 * 撤单请求
 */
void DemoTrader::reqCancelOrder() {
  INFOPRINT("--------------------------CANCEL BEGIN--------------------------");
  resetEventFlag(false);
  CXeleReqOrderActionField ActionReq;
  memset(&ActionReq, 0, sizeof(CXeleReqOrderActionField));
  ActionReq.OrigSysID = m_maxOriginOrderID;
  ActionReq.UserLocalID = m_maxLocalID++;
  ActionReq.Operway = API_OPERWAY;
  m_userApi->reqCancelOrder(ActionReq, m_requestID++);
  waitRspEvent();
  INFOPRINT("--------------------------CANCEL END--------------------------\n");
}

void DemoTrader::reqCombOrder(char side) {
  INFOPRINT("-----------------------COMB ORDER BEGIN-----------------------");
  resetEventFlag(false);
  memset(&m_reqComOrderPkt, 0, sizeof(CXeleReqOptionCombInsertField));
  m_reqComOrderPkt.UserLocalID = m_maxLocalID++;
  m_reqComOrderPkt.OrderMode = XELE_ORDER_MODE_USER;
  m_reqComOrderPkt.OwnerType = XELE_OWNER_PERSONAL_TYPE;
  m_reqComOrderPkt.CombVolume = (uint16_t) atoi(m_config["combVolume"].c_str());
  m_reqComOrderPkt.CmbOrderType = side;
  if (XELE_OPTION_UNCOMB_ORDER == side) {
    strncpy(m_reqComOrderPkt.SecondaryOrderID,
            m_splitOrderID,
            min(strlen(m_splitOrderID), sizeof(m_reqComOrderPkt.SecondaryOrderID)));
  }
  m_reqComOrderPkt.StgyCmbType = (uint8_t) atoi(m_config["stgyCmbType"].c_str());
  m_reqComOrderPkt.SumLegs = 2;  ///< 目前交易所仅支持两腿
  strncpy(m_reqComOrderPkt.CombLeg[0].LegSecuritiesID, m_config["legID1"].c_str(), sizeof(TXeleSecuritiesIDType));
  strncpy(m_reqComOrderPkt.CombLeg[1].LegSecuritiesID, m_config["legID2"].c_str(), sizeof(TXeleSecuritiesIDType));
  m_reqComOrderPkt.CombLeg[0].LegSide = m_config["legSide1"][0];
  m_reqComOrderPkt.CombLeg[1].LegSide = m_config["legSide2"][0];
  m_reqComOrderPkt.CombLeg[0].Volume = m_reqComOrderPkt.CombVolume;
  m_reqComOrderPkt.CombLeg[1].Volume = m_reqComOrderPkt.CombVolume;
  m_reqComOrderPkt.CombLeg[0].CoveredOrUncovered = 0x20; ///< 注意此处需要填空格(0x20)
  m_reqComOrderPkt.CombLeg[1].CoveredOrUncovered = 0x20; ///< 注意此处需要填空格(0x20)
  memcpy(m_reqComOrderPkt.UnderlyingSecuritiesID, "159919", strlen("159919"));
  m_userApi->reqInsertCombOrder(m_reqComOrderPkt, m_requestID++);
  waitRspEvent();
  INFOPRINT("-----------------------COMB ORDER END-----------------------\n");
}

/**
 * 报单查询
 */
void DemoTrader::reqQryOrder() {
  INFOPRINT("-----------------------QUERY ORDER BEGIN----------------------");
  resetEventFlag(false);
  usleep(200000);
  CXeleReqQryOrderField qryOrder;
  memset(&qryOrder, 0, sizeof(CXeleReqQryOrderField));
  qryOrder.OrderSysID = m_maxOriginOrderID;
  m_userApi->reqQryOrder(qryOrder, m_requestID++);
  waitRspEvent();
  INFOPRINT("-----------------------QUERY ORDER END-----------------------\n");
}

/**
 * api打印消息
 */
void DemoTrader::onApiMsg(int ret, const char *strFormat, ...) {
  const int MAX_FORMATTED_STR_LEN = 2048;
  char strResult[MAX_FORMATTED_STR_LEN] = {0};

  va_list arglist;
  va_start(arglist, strFormat);
  vsprintf(strResult, strFormat, arglist);

  va_end(arglist);
  if (ret) {
    INFOPRINT("Error:%s", strResult);
  } else {
    INFOPRINT("%s", strResult);
  }
}

/**
 * manager链路断开连接应答
 */
void DemoTrader::onFrontManagerQueryDisconnected(int nReason) {
  INFOPRINT("manager disConnected, reason[%d]\n", nReason);
}

/**
 * query链路断开连接应答
 */
void DemoTrader::onFrontQueryDisconnected(int nReason) {
  INFOPRINT("query disConnected, reason[%d]\n", nReason);
}

/**
 * trade链路断开连接应答
 */
void DemoTrader::onFrontTradeDisconnected(int nReason) {
  INFOPRINT("trade disConnected, reason[%d]\n", nReason);
}

/**
 * 登陆应答
 */
void DemoTrader::onRspLogin(CXeleRspUserLoginField *pRspField, CXeleRspInfo *pRspInfo,
                            int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    m_maxLocalID = pRspField->MaxUserLocalID + 1;
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);
  }
}

/**
 * 交易链路连接应答
 */
void DemoTrader::onRspInitTrader(CXeleRspInitTraderField *pRspField, CXeleRspInfo *pRspInfo,
                                 int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);
  }
  m_rspEvent = true;
}

/**
 * 登出应答
 */
void DemoTrader::onRspLogout(CXeleRspUserLogoutField *pRspField, CXeleRspInfo *pRspInfo,
                             int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    m_maxLocalID = pRspField->MaxUserLocalID + 1;
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);
  }
  m_rspEvent = true;
}

/**
 * 报单应答
 */
void DemoTrader::onRspInsertOrder(CXeleRspOrderInsertField *pRspField, CXeleRspInfo *pRspInfo,
                                  int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);
  }
  m_rspEvent = true;

  m_maxOriginOrderID = pRspField->OrderSysID;
}

/**
 * 撤单响应
 */
void DemoTrader::onRspCancelOrder(CXeleRspOrderActionField *pRspField, CXeleRspInfo *pRspInfo,
                                  int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);
  }
  m_rspEvent = true;
}

/**
 * 报单回报
 */
void DemoTrader::onRtnOrder(CXeleRtnOrderField *pRspField, CXeleRspInfo *pRspInfo,
                            int nRequestID, bool bIsLast) {
  PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  m_rspEvent = true;
}

/**
 * 成交回报
 */
void DemoTrader::onRtnTrade(CXeleRtnTradeField *pRspField, CXeleRspInfo *pRspInfo,
                            int nRequestID, bool bIsLast) {
  PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  m_rspEvent = true;
}

/**
 * 报单错误回报
 */
void DemoTrader::onErrRtnInsertOrder(CXeleRspOrderInsertField *pRspField, CXeleRspInfo *pRspInfo,
                                     int nRequestID, bool bIsLast) {
  PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
  m_rspEvent = true;
}

/**
 * 撤单错误回报
 */
void DemoTrader::onErrRtnCancelOrder(CXeleRspOrderActionField *pRspField, CXeleRspInfo *pRspInfo,
                                     int nRequestID, bool bIsLast) {
  PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
  m_rspEvent = true;
}

/**
 * 期权组合报单响应
 */
void DemoTrader::onRspInsertCombOrder(CXeleRspOptionCombInsertField *pRspField, CXeleRspInfo *pRspInfo,
                                      int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    // 错误处理
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);
  }
  m_rspEvent = true;
}

/**
 * 期权组合报单回报
 * 解组时,若为深交,则取原组合报单的OrderExchangeID作为解组的组合策略流水号
 */
void DemoTrader::onRtnCombOrder(CXeleRtnOptionCombOrderField *pRspField, CXeleRspInfo *pRspInfo,
                                int nRequestID, bool bIsLast) {
  PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  if (m_config["Market"].c_str()[0] == XELE_MARKET_OZ && pRspField->CombOrderInfo.CmbOrderType == '1') {
    strncpy(m_splitOrderID, pRspField->OrderExchangeID, sizeof(TXeleSecondaryOrderType));
  }
  m_rspEvent = true;
}

/**
 * 期权组合成交回报
 * 解组时,若为上交，则原组合报单的SecondaryOrderID为解组的组合策略流水号
 */
void DemoTrader::onRtnCombTrade(CXeleRtnOptionCombTradeField *pRspField, CXeleRspInfo *pRspInfo,
                                int nRequestID, bool bIsLast) {
  PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  if (m_config["Market"].c_str()[0] == XELE_MARKET_OS && pRspField->CombOrderInfo.CmbOrderType == '1') {
    strncpy(m_splitOrderID, pRspField->CombOrderInfo.SecondaryOrderID, sizeof(TXeleSecondaryOrderType));
    INFOPRINT("split order id[%s]", m_splitOrderID);
  }
  m_rspEvent = true;
}

/**
 * 期权组合报单错误回报
 */
void DemoTrader::onErrRtnInsertCombOrder(CXeleRspOptionCombInsertField *pRspField, CXeleRspInfo *pRspInfo,
                                         int nRequestID, bool bIsLast) {
  PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
  m_rspEvent = true;
}

/**
 * 报单查询响应
 */
void DemoTrader::onRspQryOrder(CXeleRspQryOrderField *pRspField, CXeleRspInfo *pRspInfo,
                               int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);
  }
  m_rspEvent = true;
}

/**
 * 成交单查询响应
 */
void DemoTrader::onRspQryTrade(CXeleRspQryTradeField *pRspField, CXeleRspInfo *pRspInfo,
                               int nRequestID, bool bIsLast) {
  if (pRspInfo->ErrorID == 0) {
    PRINT_RSP(pRspInfo, nRequestID, bIsLast);
  } else {
    PRINT_RSP_ERR(pRspInfo, nRequestID, bIsLast);
    // 错误处理
    INFOPRINT("error occur[%u]", pRspInfo->ErrorID);

  }
  m_rspEvent = true;

}

int runDemoProcess() {

  ///  创建api类对象, 使用时请注意本api非线程安全
  auto newApi = XeleSecuritiesTraderApi::createTraderApi();
  if (!newApi) {
    return -1;
  }

  ///  创建回调对象
  auto newTrader = new DemoTrader(newApi);

  ///  注册回调对象
  newApi->registerSpi(newTrader);

  ///  登陆
  if (newTrader->reqLogin() < 0) {
    return -1;
  }

  ///  报买单
  newTrader->reqOrder(XELE_ORDER_BUY);

  ///  撤上个买单
  newTrader->reqCancelOrder();

  ///  查询报单
  newTrader->reqQryOrder();

  ///  组合保证金报单(组合)
  newTrader->reqCombOrder(XELE_OPTION_COMB_ORDER);

  ///  组合保证金报单(拆分)
  newTrader->reqCombOrder(XELE_OPTION_UNCOMB_ORDER);

  ///  登出
  newTrader->reqLogout();

  ///  释放api对象
  newApi->release();

  ///  释放回调对象
  delete newTrader;

  return 0;
}

int main() {
  string msg;
  if (runDemoProcess() < 0) {
    INFOPRINT("run demo failed.");
    return 0;
  }

  INFOPRINT("run demo finish.");

  return 0;
}
