/**
 * @file global.h
 * @author root
 * @brief 全局数据定义
 * @date 25-7-16
 *
 * 详细的文件描述或注意事项可以放在这里。
 */
#ifndef SECURITY_TRADER_API_GLOBAL_H
#define SECURITY_TRADER_API_GLOBAL_H

#include <string>
#include <vector>
#include <stdint.h>
#include <map>

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

/// Account Info Structure
struct AccountInfo {
  std::string accountId;
  std::string password;
};

/// Order Item
struct OrderInfo {
  uint32_t orderLocalId;
};

/// Login Status
enum TLoginStatus {
  Login_Initialize = 0,
  Login_LoginOK,
  Login_LoginFailed,
  Login_LogoutOK,
  Login_LogoutFailed
};

/// Trade Connection Status
enum TTradeStatus {
  Trade_Initialize = 0,
  /// Modify By TradeClient
      Trade_Connected,
  Trade_Disconnected,
  /// Modify By Spi
      Trade_TradeOK,
  Trade_TradeFailed
};

enum TcpType {
  ManagerTcp = 1,
  CounterQueryTcp = 2,
  CounterTradeTcp = 3
};

/// 主要管理此Demo全局使用到的一些数据, 和维护一些状态。
/// Global Data Manager
class GlobalDataManager {
 public:
  static GlobalDataManager& GetInstance() {
    static GlobalDataManager instance;
    return instance;
  }

  /// 工具：
  /// 将柜台返回的Url地址解析为ip和port
  bool DecodeURL(std::string& uri, std::string& ip, std::string& port) {
    auto pre_idx = uri.find("://");
    auto suf_idx = uri.rfind(':');
    if (pre_idx == std::string::npos || suf_idx == std::string::npos) {
      return false;
    }
    auto conn_type = uri.substr(0, pre_idx);
    ip = uri.substr(pre_idx + 3, suf_idx - 3 - pre_idx);
    port = uri.substr(suf_idx + 1);
    return true;
  }

  /// Node
  void setNode(int node) {
    _node = node;
  }

  int getNode() const {
    return _node;
  }

  /// Market
  void setMarket(char market) {
    _market = market;
  }

  char getMarket() const {
    return _market;
  }

  /// Account Info
  void setAccountInfo(const std::string &accountId, const std::string &password) {
    _accountInfo.accountId = accountId;
    _accountInfo.password = password;
  }

  const AccountInfo& getAccountInfo() const {
    return _accountInfo;
  }

  /// Order Table
  bool orderTableEmpty() const {
    return _orderTable.empty();
  }

  void insertOrderTable(const OrderInfo &orderItem) {
    _orderTable.push_back(orderItem);
  }

  const std::vector<OrderInfo>& getOrderTable() const {
    return _orderTable;
  }

  /// SessionId
  void setManagerSessionId(uint16_t sessionId) {
    _managerSessionId = sessionId;
  }

  uint16_t getManagerSessionId() const {
    return _managerSessionId;
  }

  void setCounterSessionId(uint16_t sessionId) {
    _counterSessionId = sessionId;
  }

  uint16_t getCounterSessionId() const {
    return _counterSessionId;
  }

  /// Token
  void setManagerToken(uint16_t token) {
    _managerToken = token;
  }

  uint16_t getManagerToken() const {
    return _managerToken;
  }

  void setCounterToken(uint16_t token) {
    _counterToken = token;
  }

  uint16_t getCounterToken() const {
    return _counterToken;
  }

  /// Login Status
  void setLoginStatus(int loginStatus) {
    _loginStatus = loginStatus;
  }

  int getLoginStatus() const {
    return _loginStatus;
  }

  bool isLogin() const {
    return _loginStatus == TLoginStatus::Login_LoginOK;
  }

  /// Trade Status
  void setTradeStatus(int tradeStatus) {
    _tradeStatus = tradeStatus;
  }

  int getTradeStatus() const {
    return _tradeStatus;
  }

  bool canTrade() const {
    return _tradeStatus == TTradeStatus::Trade_TradeOK;
  }

  /// RequestID Inc After Return
  int requestId() {
    return _requestId++;
  }

  /// MaxLocalID
  void setMaxLocalId(int maxLocalId) {
    /// 登录后获取到的最大值需要加1
    _maxLocalId = maxLocalId + 1;
  }

  int maxLocalId() {
    return _maxLocalId++;
  }

  void setManagerPort(uint16_t port) {
    _managerPort = port;
  }

  uint16_t getManagerPort() {
    return _managerPort;
  }

  void setCounterQueryPort(uint16_t port) {
    _counterQueryPort = port;
  }

  uint16_t getCounterQueryPort() {
    return _counterQueryPort;
  }

  void setCounterTradePort(uint16_t port) {
    _counterTradePort = port;
  }

  uint16_t getCounterTradePort() {
    return _counterTradePort;
  }

  void setManagerIp(std::string ip) {
    _managerIp = std::move(ip);
  }

  std::string getManagerIp() {
    return _managerIp;
  }

  void setCounterQueryIp(std::string ip) {
    _counterQueryIp = std::move(ip);
  }

  std::string getCounterQueryIp() {
    return _counterQueryIp;
  }

  void setCounterTradeIp(std::string ip) {
    _counterTradeIp = std::move(ip);
  }

  std::string getCounterTradeIp() {
    return _counterTradeIp;
  }

  unsigned int getSeqNoManager() {
    return _seqNoManager++;
  }

  unsigned int getSeqNoCounterQuery() {
    return _seqNoCounterQuery++;
  }

  unsigned int getSeqNoCounterTrade() {
    return _seqNoCounterTrade++;
  }

  char getDirection() const {
    return Direction;
  }
  void setDirection(char Direction) {
    GlobalDataManager::Direction = Direction;
  }
  double getLimitPrice() const {
    return LimitPrice;
  }
  void setLimitPrice(double LimitPrice) {
    GlobalDataManager::LimitPrice = LimitPrice;
  }
  uint32_t getVolume() const {
    return Volume;
  }
  void setVolume(uint32_t Volume) {
    GlobalDataManager::Volume = Volume;
  }
  const std::string &getSecuritiesID() const {
    return SecuritiesID;
  }
  void setSecuritiesID(const std::string &SecuritiesID) {
    GlobalDataManager::SecuritiesID = SecuritiesID;
  }
  ulong getCounterHeartbeatInterval() const {
    return CounterHeartbeatInterval;
  }
  void setCounterHeartbeatInterval(ulong CounterHeartbeatInterval) {
    GlobalDataManager::CounterHeartbeatInterval = CounterHeartbeatInterval;
  }
  ulong getCounterHeartbeatTimeout() const {
    return CounterHeartbeatTimeout;
  }
  void setCounterHeartbeatTimeout(ulong CounterHeartbeatTimeout) {
    GlobalDataManager::CounterHeartbeatTimeout = CounterHeartbeatTimeout;
  }
  int getManagerHeartBeatInterval() const {
    return ManagerHeartBeatInterval;
  }
  void setManagerHeartBeatInterval(int ManagerHeartBeatInterval) {
    GlobalDataManager::ManagerHeartBeatInterval = ManagerHeartBeatInterval;
  }
  int getManagerHeartBeatTimeout() const {
    return ManagerHeartBeatTimeout;
  }
  void setManagerHeartBeatTimeout(int ManagerHeartBeatTimeout) {
    GlobalDataManager::ManagerHeartBeatTimeout = ManagerHeartBeatTimeout;
  }
  const std::string &getTradeSourceIp() const {
    return TradeSourceIp;
  }
  void setTradeSourceIp(const std::string &TradeSourceIp) {
    GlobalDataManager::TradeSourceIp = TradeSourceIp;
  }
  uint16_t getTradeSoucrePort() const {
    return TradeSourcePort;
  }
  void setTradeSourcePort(uint16_t TradeSoucrePort) {
    GlobalDataManager::TradeSourcePort = TradeSoucrePort;
  }
  const std::string &getPcPrefix() const {
    return PcPrefix;
  }
  void setPcPrefix(const std::string &PcPrefix) {
    GlobalDataManager::PcPrefix = PcPrefix;
  }
  const std::string &getHdPartitionInfo() const {
    return HdPartitionInfo;
  }
  void setHdPartitionInfo(const std::string &HdPartitionInfo) {
    GlobalDataManager::HdPartitionInfo = HdPartitionInfo;
  }
  const std::string &getBusinessCode() const {
    return BusinessCode;
  }
  void setBusinessCode(const std::string &BusinessCode) {
    GlobalDataManager::BusinessCode = BusinessCode;
  }
  const std::string &getAppIDExt() const {
    return AppIDExt;
  }
  void setAppIDExt(const std::string &AppIDExt) {
    GlobalDataManager::AppIDExt = AppIDExt;
  }
  const std::string &getClientIp() const {
    return ClientIp;
  }
  void setClientIp(const std::string &ClientIp) {
    GlobalDataManager::ClientIp = ClientIp;
  }
  const std::string &getClientMac() const {
    return ClientMac;
  }
  void setClientMac(const std::string &ClientMac) {
    GlobalDataManager::ClientMac = ClientMac;
  }
  const std::string &getAppID() const {
    return AppID;
  }
  void setAppID(const std::string &AppID) {
    GlobalDataManager::AppID = AppID;
  }
  const std::string &getOperWay() const {
    return OperWay;
  }
  void setOperWay(const std::string &_operWay) {
    GlobalDataManager::OperWay = _operWay;
  }
  const std::string &getHard_disk_serial() const {
    return hard_disk_serial;
  }
  void setHard_disk_serial(const std::string &hard_disk_serial) {
    GlobalDataManager::hard_disk_serial = hard_disk_serial;
  }
  const std::string &getCpu_serial() const {
    return cpu_serial;
  }
  void setCpu_serial(const std::string &cpu_serial) {
    GlobalDataManager::cpu_serial = cpu_serial;
  }
  const std::string &getHostname() const {
    return hostname;
  }
  void setHostname(const std::string &hostname) {
    GlobalDataManager::hostname = hostname;
  }
  const std::string &getAllSuperviseInfo() const {
    return allSuperviseInfo;
  }
  void setAllSuperviseInfo(const std::string &allSuperviseInfo) {
    GlobalDataManager::allSuperviseInfo = allSuperviseInfo;
  }
  bool isIsConnectHardTrade() const {
    return isConnectHardTrade;
  }
  void setIsConnectHardTrade(bool isConnectHardTrade) {
    GlobalDataManager::isConnectHardTrade = isConnectHardTrade;
  }

 public:
  GlobalDataManager(const GlobalDataManager&) = delete;
  GlobalDataManager& operator=(const GlobalDataManager&) = delete;

 private:
  GlobalDataManager() {
    _node = 0;
    _market = 0;
    _managerSessionId = 0;
    _counterSessionId = 0;
    _managerToken = 0;
    _counterToken = 0;
    _loginStatus = TLoginStatus::Login_Initialize;
    _tradeStatus = TTradeStatus::Trade_Initialize;
    _requestId = 0;
    _maxLocalId = 0;
    _managerPort = 0;
    _counterQueryPort = 0;
    _counterTradePort = 0;

    _seqNoManager = 0;
    _seqNoCounterQuery = 0;
    _seqNoCounterTrade = 0;
  }

 private:
  /// 登录节点
  int                     _node;
  /// 交易所标识
  char                    _market;
  /// 账户信息
  AccountInfo             _accountInfo;
  /// 报单表, 此Demo中只演示了撤单, 只需要OrderSysID就行
  std::vector<OrderInfo>  _orderTable;

  /// Auth Info
  uint16_t _managerSessionId;
  uint16_t _managerToken;
  uint16_t _counterSessionId;
  uint16_t _counterToken;

  unsigned int _seqNoManager;
  unsigned int _seqNoCounterQuery;
  unsigned int _seqNoCounterTrade;

  /// loginStatus: modify by Spi::onLogin
  int _loginStatus;
  /// tradeStatus: modify by Spi::onInitTrader And TradeClient
  int _tradeStatus;

  /// Global RequestId
  /// 报文头部需要这个字段, 每次+1
  int _requestId;
  /// 第一次设置为登录响应中的MaxUserLocalID，之后每次发送报单报文中+1
  int _maxLocalId;

  /// manager端口号
  uint16_t _managerPort;
  /// manager地址
  std::string _managerIp;
  /// 柜台查询链路端口号
  uint16_t _counterQueryPort;
  /// 柜台查询链路地址
  std::string _counterQueryIp;
  /// 柜台交易链路端口号
  uint16_t _counterTradePort;
  /// 柜台交易链路地址
  std::string _counterTradeIp;

  std::string AppID;
  std::string ClientIp;
  std::string ClientMac;
  std::string OperWay;
  std::string PcPrefix;
  std::string HdPartitionInfo;
  std::string BusinessCode;
  std::string AppIDExt;
  std::string TradeSourceIp;
  uint16_t TradeSourcePort;
  int ManagerHeartBeatInterval;
  int ManagerHeartBeatTimeout;
  ulong CounterHeartbeatInterval;
  ulong CounterHeartbeatTimeout;
  std::string SecuritiesID;
  double LimitPrice;
  uint32_t Volume;
  char Direction;
  std::string hard_disk_serial;
  std::string cpu_serial;
  std::string hostname;
  std::string allSuperviseInfo;
  bool isConnectHardTrade;
};

#endif //SECURITY_TRADER_API_GLOBAL_H
