/**
 * @file responseHandler.h
 * @author root
 * @brief 回报消息处理
 * @date 25-7-16
 *
 * 详细的文件描述或注意事项可以放在这里。
 */
#ifndef SECURITY_TRADER_API_RESPONSEHANDLER_H
#define SECURITY_TRADER_API_RESPONSEHANDLER_H

#include <iostream>
#include <cstring>
#include <iomanip>

#include "global.h"
#include "errorCode_Bare.h"
#include "XeleSecuritiesUserApiStruct_Bare.h"

/// Base Interface
class responseHandler {
 public:
  responseHandler() = default;

  virtual ~responseHandler() = default;

  /// Interface
  virtual int doResponse(void *buf) = 0;
};

class RspManagerUserLoginHandle : public responseHandler {
 public:
  ~RspManagerUserLoginHandle() override = default ;
  int doResponse(void *buf) override{
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspField = (CXeleRspUserLoginManagerField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      std::cout << "========onRspLoginManager=======" << std::endl;
      std::cout << "TradingDay:" << pRspField->TradingDay << std::endl;
      std::cout << "LoginTime:" << pRspField->LoginTime << std::endl;
      std::cout << "AccountID:" << pRspField->AccountID << std::endl;
      std::cout << "SessionID:" << pRspField->SessionID << std::endl;
      std::cout << "Token:" << pRspField->Token << std::endl;
      std::cout << "Operway:" << pRspField->Operway << std::endl;
      std::cout << "CounterUrl:" << pRspField->CounterUrl << std::endl;
      std::cout << "SubClientIndex:" << (unsigned int) pRspField->SubClientIndex << std::endl;
      std::cout << "HeartBeatInterval:" << pRspField->HeartBeatInterval << std::endl;
      std::cout << "HeartBeatTimeout:" << pRspField->HeartBeatTimeout << std::endl;
      std::cout << "IsInternetConnect:" << pRspField->IsInternetConnect << std::endl;

      /// SessionId和Token字段在与manager的后续交互中要进行校验，需要在本地保存
      GlobalDataManager::GetInstance().setManagerSessionId(pRspField->SessionID);
      GlobalDataManager::GetInstance().setManagerToken(pRspField->Token);

      /// CounterUrl是柜台查询链路的地址
      std::string CounterUrl, ip, port;
      CounterUrl = std::string(pRspField->CounterUrl);
      GlobalDataManager::GetInstance().DecodeURL(CounterUrl, ip, port);
      GlobalDataManager::GetInstance().setCounterQueryIp(ip);
      GlobalDataManager::GetInstance().setCounterQueryPort(std::atoi(port.c_str()));
      /// 心跳参数也需要保存，后续根据该参数进行心跳超时检测
      GlobalDataManager::GetInstance().setManagerHeartBeatInterval(pRspField->HeartBeatInterval);
      GlobalDataManager::GetInstance().setManagerHeartBeatTimeout(pRspField->HeartBeatTimeout);
    } else {
      PRINT_INFO("Login Manager failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

class RspManagerUserLogoutHandle : public responseHandler {
 public:
  ~RspManagerUserLogoutHandle() override = default;
  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspField = (CXeleRspUserLogoutManagerField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      std::cout << "========onRspLogoutManager=======" << std::endl;
      std::cout << "TradingDay:" << pRspField->TradingDay << std::endl;
      std::cout << "LogoutTime:" << pRspField->LogoutTime << std::endl;
      std::cout << "AccountID:" << pRspField->AccountID << std::endl;
      std::cout << "SessionID:" << pRspField->SessionID << std::endl;

    } else {
      PRINT_INFO("Logout Manager failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

class RspUserLoginHandler : public responseHandler {
 public:
  ~RspUserLoginHandler() override = default;
  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspField = (CXeleRspUserLoginField*)((char *)buf + sizeof(CXeleFairRspHeadField));
      std::cout << "========onRspLogin=======" << std::endl;
      std::cout << "TradingDay:" << pRspField->TradingDay << std::endl;
      std::cout << "LoginTime:" << pRspField->LoginTime << std::endl;
      std::cout << "MaxOrderLocalID:" << pRspField->MaxUserLocalID << std::endl;
      std::cout << "AccountID:" << pRspField->AccountID << std::endl;
      std::cout << "SessionID:" << pRspField->SessionID << std::endl;
      std::cout << "Token:" << pRspField->Token << std::endl;
      std::cout << "node:" << (unsigned int)pRspField->SubClientIndex << std::endl;
      std::cout << "TradeDestIp:" << pRspField->TradeDestIp << std::endl;
      std::cout << "TradeDestPort:" << pRspField->TradeDestPort << std::endl;
      std::cout << "TradeFlag:" << pRspField->TradeFlag << std::endl;
      std::cout << "Operway:" << pRspField->Operway << std::endl;
      std::cout << "Market:" << pRspField->Market << std::endl;
      std::cout << "TradeType:" << pRspField->TradeType << std::endl;
      std::cout << "HeartBeatInterval:" << pRspField->HeartBeatInterval << std::endl;
      std::cout << "HeartBeatTimeout:" << pRspField->HeartBeatTimeout << std::endl;
      std::cout << "IsInternetConnect:" << pRspField->IsInternetConnect << std::endl;

      /// SessionId和Token字段在与counter的后续交互中要进行校验，需要在本地保存
      GlobalDataManager::GetInstance().setCounterSessionId(pRspField->SessionID);
      GlobalDataManager::GetInstance().setCounterToken(pRspField->Token);

      /// 交易链路的地址
      std::string ip = std::string(reinterpret_cast<const char *>(pRspField->TradeDestIp), 0 , sizeof(TXeleTradeIPType));
      GlobalDataManager::GetInstance().setCounterTradeIp(ip);
      GlobalDataManager::GetInstance().setCounterTradePort(pRspField->TradeDestPort);
      /// 已经使用的本地报单最大值，报单时要进行填写
      GlobalDataManager::GetInstance().setMaxLocalId(pRspField->MaxUserLocalID);
      /// 心跳参数也需要保存，后续根据该参数进行心跳超时检测
      GlobalDataManager::GetInstance().setCounterHeartbeatInterval(pRspField->HeartBeatInterval);
      GlobalDataManager::GetInstance().setCounterHeartbeatTimeout(pRspField->HeartBeatTimeout);

      /// 当前连接的是软件链路还是硬件链路
      GlobalDataManager::GetInstance().setIsConnectHardTrade(pRspField->TradeType == TRADETYPEOFFPGA);
    } else {
      PRINT_INFO("Login counter failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }

    return pRspHead->ErrorID;
  }
};

class RspInitTraderHandler : public responseHandler {
 public:
  ~RspInitTraderHandler() override = default;
  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspField = (CXeleRspInitTraderField*)((char *)buf + sizeof(CXeleFairRspHeadField));
      PRINT_INFO("====================RspInitTrader====================");
      PRINT_INFO("AccountID=%.15s", pRspField->AccountID);
    } else {
      PRINT_INFO("initTrader failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

/// 报单响应处理
class RspOrderInsertHandler: public responseHandler {
 public:
  ~RspOrderInsertHandler() override = default;

  int doResponse(void *buf) override{
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspOrderInsert = (CXeleRspOrderInsertField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      PRINT_INFO("====================RspOrderInsert====================");

      PRINT_INFO("OrderSysID=%d", pRspOrderInsert->OrderSysID);
      PRINT_INFO("UserLocalID=%d", pRspOrderInsert->UserLocalID);
      PRINT_INFO("SecuritiesID=%.8s", pRspOrderInsert->SecuritiesID);
      PRINT_INFO("Direction=%c", pRspOrderInsert->Direction);
      PRINT_INFO("LimitPrice=%lf", pRspOrderInsert->LimitPrice);
      PRINT_INFO("Volume=%d", pRspOrderInsert->Volume);
      PRINT_INFO("StrOrderSysID=%.10s", pRspOrderInsert->StrOrderSysID);
      PRINT_INFO("AccountID=%.15s", pRspOrderInsert->AccountID);
      PRINT_INFO("ErrorID=%d", pRspOrderInsert->ErrorID);

      PRINT_INFO("======================================================");
    } else {
      PRINT_INFO("RspOrderInsert failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

/// 报单错误处理
class ErrOrderInsertHandler: public responseHandler {
 public:
  ~ErrOrderInsertHandler() override = default;

  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspOrderInsert = (CXeleRspOrderInsertField *) ((char *) buf + sizeof(CXeleFairRspHeadField));

      PRINT_INFO("====================ErrOrderInsert====================");

      PRINT_INFO("OrderSysID=%d", pRspOrderInsert->OrderSysID);
      PRINT_INFO("UserLocalID=%d", pRspOrderInsert->UserLocalID);
      PRINT_INFO("SecuritiesID=%.8s", pRspOrderInsert->SecuritiesID);
      PRINT_INFO("Direction=%c", pRspOrderInsert->Direction);
      PRINT_INFO("LimitPrice=%lf", pRspOrderInsert->LimitPrice);
      PRINT_INFO("Volume=%d", pRspOrderInsert->Volume);
      PRINT_INFO("StrOrderSysID=%.10s", pRspOrderInsert->StrOrderSysID);
      PRINT_INFO("AccountID=%.15s", pRspOrderInsert->AccountID);
      PRINT_INFO("ErrorID=%d", pRspOrderInsert->ErrorID);

      PRINT_INFO("======================================================");
    } else {
      PRINT_INFO("ErrOrderInsert failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

/// 报单回报处理
class RtnOrderHandler: public responseHandler {
 public:
  ~RtnOrderHandler() override = default;

  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRtnOrder = (CXeleRtnOrderField *) ((char *) buf + sizeof(CXeleFairRspHeadField));

      PRINT_INFO("====================RtnOrder====================");

      PRINT_INFO("OrderSysID=%d", pRtnOrder->OrderSysID);
      PRINT_INFO("UserLocalID=%d", pRtnOrder->UserLocalID);
      PRINT_INFO("OrderExchangeID=%.16s", pRtnOrder->OrderExchangeID);
      PRINT_INFO("SecuritiesID=%.8s", pRtnOrder->SecuritiesID);
      PRINT_INFO("Direction=%c", pRtnOrder->Direction);
      PRINT_INFO("LimitPrice=%lf", pRtnOrder->LimitPrice);
      PRINT_INFO("Volume=%d", pRtnOrder->Volume);
      PRINT_INFO("StrOrderSysID=%.10s", pRtnOrder->StrOrderSysID);
      PRINT_INFO("TransactTime=%.21s", pRtnOrder->TransactTime);
      PRINT_INFO("TradeVolume=%d", pRtnOrder->TradeVolume);
      PRINT_INFO("LeavesVolume=%d", pRtnOrder->LeavesVolume);
      PRINT_INFO("OrderStatus=%c", pRtnOrder->OrderStatus);
      PRINT_INFO("AccountID=%s", pRtnOrder->AccountID);

      PRINT_INFO("================================================");
      /// 收到此回报, 代表报单成功, 已到交易所。把OrderSysID存入报单表, 给下次撤单使用。
      OrderInfo order = {
          pRtnOrder->OrderSysID
      };
      /// 为demo进行撤单演示做准备
      GlobalDataManager::GetInstance().insertOrderTable(order);
    } else {
      PRINT_INFO("RtnOrder failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }


    return pRspHead->ErrorID;
  }
};

/// 成交回报处理
class RtnTradeHandler: public responseHandler {
 public:
  ~RtnTradeHandler() override = default;

  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRtnTrade = (CXeleRtnTradeField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      PRINT_INFO("====================RtnTrade====================");

      PRINT_INFO("OrderSysID=%d", pRtnTrade->OrderSysID);
      PRINT_INFO("UserLocalID=%d", pRtnTrade->UserLocalID);
      PRINT_INFO("OrderExchangeID=%.16s", pRtnTrade->OrderExchangeID);
      PRINT_INFO("SecuritiesID=%.8s", pRtnTrade->SecuritiesID);
      PRINT_INFO("Direction=%c", pRtnTrade->Direction);
      PRINT_INFO("LimitPrice=%lf", pRtnTrade->LimitPrice);
      PRINT_INFO("Volume=%d", pRtnTrade->Volume);
      PRINT_INFO("StrOrderSysID=%.10s", pRtnTrade->StrOrderSysID);
      PRINT_INFO("TransactTime=%.21s", pRtnTrade->TransactTime);
      PRINT_INFO("TradeVolume=%d", pRtnTrade->TradeVolume);
      PRINT_INFO("LeavesVolume=%d", pRtnTrade->LeavesVolume);
      PRINT_INFO("OrderStatus=%c", pRtnTrade->OrderStatus);
      PRINT_INFO("AccountID=%s", pRtnTrade->AccountID);
      PRINT_INFO("ExecID=%.16s", pRtnTrade->ExecID);

      PRINT_INFO("================================================");
    } else {
      PRINT_INFO("RtnTrade failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }

    return pRspHead->ErrorID;
  }
};

/// 撤单应答处理
class RspOrderActionHandler: public responseHandler {
 public:
  ~RspOrderActionHandler() override = default;

  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspOrderAction = (CXeleRspOrderActionField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      PRINT_INFO("====================RspOrderAction====================");

      PRINT_INFO("OrderSysID=%d", pRspOrderAction->OrderSysID);
      PRINT_INFO("UserLocalID=%d", pRspOrderAction->UserLocalID);
      PRINT_INFO("AccountID=%.15s", pRspOrderAction->AccountID);
      PRINT_INFO("ErrorID=%d", pRspOrderAction->ErrorID);

      PRINT_INFO("======================================================");
    } else {
      PRINT_INFO("OrderAction failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

/// 撤单错误处理
class ErrOrderActionHandler: public responseHandler {
 public:
  ~ErrOrderActionHandler() override = default;

  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspOrderAction = (CXeleRspOrderActionField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      PRINT_INFO("====================ErrOrderAction====================");

      PRINT_INFO("OrderSysID=%d", pRspOrderAction->OrderSysID);
      PRINT_INFO("UserLocalID=%d", pRspOrderAction->UserLocalID);
      PRINT_INFO("AccountID=%.15s", pRspOrderAction->AccountID);
      PRINT_INFO("ErrorID=%d", pRspOrderAction->ErrorID);

      PRINT_INFO("======================================================");
    } else {
      PRINT_INFO("OrderAction failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

/// 报单查询处理
class RspOrderQueryHandler : public responseHandler {
 public:
  ~RspOrderQueryHandler() override = default;

  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspField = (CXeleRspQryOrderField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      PRINT_INFO("====================RspOrderQuery====================");

      std::cout << "UserLocalID:" << pRspField->UserLocalID << std::endl;
      std::cout << "SecurityID:" << std::string(pRspField->SecuritiesID, strlen(pRspField->SecuritiesID)) << std::endl;
      std::cout << "Direction:" << pRspField->Direction << std::endl;
      std::cout << "CmbOffsetFlag:" << pRspField->CmbOffsetFlag << std::endl;
      std::cout << "LimitPrice:" << std::fixed << std::setprecision(4) << pRspField->LimitPrice << std::endl;
      std::cout << "Volume:" << pRspField->Volume << std::endl;
      std::cout << "OrderType:" << pRspField->OrderType << std::endl;
      std::cout << "TimeCondition:" << pRspField->TimeCondition << std::endl;
      std::cout << "Market:" << pRspField->Market << std::endl;
      std::cout << "Operway:" << pRspField->Operway << std::endl;
      std::cout << "OrderSysID:" << pRspField->OrderSysID << std::endl;
      std::cout << "OrderExchangeID:" << std::string(pRspField->OrderExchangeID,sizeof(pRspField->OrderExchangeID)) << std::endl;
      std::cout << "TransactTime:" << pRspField->TransactTime << std::endl;
      std::cout << "DiscretionPrice:" << std::fixed << std::setprecision(4) << pRspField->DiscretionPrice << std::endl;
      std::cout << "TradeVolume:" << pRspField->TradeVolume << std::endl;
      std::cout << "LeavesVolume:" << pRspField->LeavesVolume << std::endl;
      std::cout << "OrderStatus:" << pRspField->OrderStatus << std::endl;
      std::cout << "Commision:" << std::fixed << std::setprecision(4) << pRspField->Commission << std::endl;
      std::cout << "StampTax:" << std::fixed << std::setprecision(4) << pRspField->StampTax << std::endl;
      std::cout << "Transfer:" << std::fixed << std::setprecision(4) << pRspField->Transfer << std::endl;
      std::cout << "TrafficFee:" << std::fixed << std::setprecision(4) << pRspField->TrafficFee << std::endl;
      std::cout << "TotalFee:" << std::fixed << std::setprecision(4) << pRspField->TotalFee << std::endl;
      std::cout << "AccountID:" << pRspField->AccountID << std::endl;
      std::cout << "node:" << (unsigned int)pRspField->SubClientIndex << std::endl;
      std::cout << "BusinessUnit:" << std::string(pRspField->BusinessUnit, sizeof(pRspField->BusinessUnit)) << std::endl;
      std::cout << "StrOrderSysID:" << std::string(pRspField->StrOrderSysID, sizeof(pRspField->StrOrderSysID)) << std::endl;
      std::cout << "OrderMessageId:" << (unsigned int)pRspField->OrderMessageId << std::endl;
      std::cout << "SecuritiesType:" << (short)pRspField->SecuritiesType << std::endl;
      std::cout << "PreOrderFlag:" << pRspField->PreOrderFlag << std::endl;
      std::cout << "EndNum:" << (unsigned int)pRspField->EndNum << std::endl;
      std::cout << "QryAgain:" << (bool)pRspField->QryAgain << std::endl;
      std::cout << "QryTotalNum:" << pRspField->QryTotalNum << std::endl;
      std::cout << "InvestorID:" << std::string(pRspField->InvestorID, sizeof(TXeleInvestorIDType)) << std::endl;
      std::cout << "CustID:" << pRspField->CustID << std::endl;
      std::cout << "TradeAmount:" << pRspField->TradeAmount << std::endl;
      std::cout << "UnSyncOrderFlag:" << pRspField->UnSyncOrderFlag << std::endl;
      std::cout << "CoveredOrUncovered:" << pRspField->CoveredOrUncovered << std::endl;
      std::cout << "OrigStrOrderSysID:" << std::string(pRspField->OrigStrOrderSysID, sizeof(pRspField->OrigStrOrderSysID)) << std::endl;
      std::cout << "OrderSource:" << pRspField->OrderSource << std::endl;
      std::cout << "ExchangeFrontNo:" << pRspField->ExchangeFrontNo << std::endl;
      std::cout << "OperWayEx:" << std::string(pRspField->OperWayEx, sizeof(pRspField->OperWayEx)) << std::endl;

      PRINT_INFO("======================================================");
    } else {
      PRINT_INFO("OrderQuery failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }

    return pRspHead->ErrorID;
  }
};

class RspCounterUserLogoutHandle : public responseHandler {
 public:
  ~RspCounterUserLogoutHandle() override = default;
  int doResponse(void *buf) override {
    auto pRspHead = (CXeleFairRspHeadField*) buf;
    if (pRspHead->ErrorID == SHARE_NO_ERROR) {
      auto pRspField = (CXeleRspUserLogoutField*)((char *)buf + sizeof(CXeleFairRspHeadField));

      std::cout << "========onRspLogoutCounter=======" << std::endl;
      std::cout << "TradingDay:" << pRspField->TradingDay << std::endl;
      std::cout << "LogoutTime:" << pRspField->LogoutTime << std::endl;
      std::cout << "MaxUserLocalID:" << pRspField->MaxUserLocalID << std::endl;
      std::cout << "AccountID:" << pRspField->AccountID << std::endl;
      std::cout << "SessionID:" << pRspField->SessionID << std::endl;

    } else {
      PRINT_INFO("Logout Counter failed, errorId %d, errorMsg %s",
                 pRspHead->ErrorID,
                 ApiErrorMsg::ParseMsg(pRspHead->ErrorID, &pRspHead->Market));
    }
    return pRspHead->ErrorID;
  }
};

#endif //SECURITY_TRADER_API_RESPONSEHANDLER_H
