//+------------------------------------------------------------------+
//|                                             MetaTrader AutoHedge |
//|                          Copyright 2001-2014, KAB Software Corp. |
//|                                                http://www.kab.hk |
//+------------------------------------------------------------------+
#pragma once

#include <vector>
#include <map>
#include "TcpServerProcess.h"
#include "..\public\MT4ManagerAPI.h"
#include <mutex>
#include <vector>
#include <thread>
#include "json.hpp"
using json = nlohmann::json;
#include "logger.h"
using namespace tools;
//#pragma comment(lib, "ws2_32")

const int           ERROR_JSON_FAIL = -2;//json格式解析错误

const int           ERROR_GET_OPEN_USER_FAIL = -21;//获取开仓用户信息失败
const int          	ERROR_GET_OPEN_GROUP_FAIL = -22;//获取开仓组信息失败
const int          	ERROR_GET_OPEN_PRICES_FAIL = -23;//获取开仓价格信息失败
const int         	ERROR_OPEN_INTERFACE_FAIL = -24;//调用开仓接口失败
const int         	ERROR_GET_OPEN_TRADE_FAIL = -25;//获取开仓单信息失败
const int         	ERROR_GET_OPEN_LOTSTEP_FAIL = -26;//获取kaic lotstep失败


const int			ERROR_CLOSE_SYMBOL_MISMATCH = -31;//品种不匹配
const int			ERROR_TRADE_ALREADY_CLOSE = -32;//单已经平仓
const int           ERROR_GET_CLOSE_USER_FAIL = -33;//获取平仓用户信息失败
const int          	ERROR_GET_CLOSE_GROUP_FAIL = -34;//获取平仓组信息失败
const int          	ERROR_GET_CLOSE_PRICES_FAIL = -35;//获取平仓价格信息失败
const int         	ERROR_CLOSE_INTERFACE_FAIL = -36;//调用平仓接口失败
const int         	ERROR_GET_CLOSE_TRADE_FAIL = -37;//获取平仓单信息失败

const int         	ERROR_JSON_LEN = -41;						//长度过长
const int         	ERROR_JSON_TYPE = -42;						//不存在的type
const int         	ERROR_JSON_NAME = -43;						//不存在的name
const int         	ERROR_JSON_MASTER = -44;						//不存在的master


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct MT4_MSG
{
	int code;
	int type;
	TradeRecord tr;
	UserRecord ur;
	RequestInfo rinfo;
	MarginLevel ml;
};
enum { TCP_HEART = 0,TCP_TRADE,TCP_STATUS};
enum { MT4_TRADE_OPEN = 0, MT4_TRADE_CLOSE, MT4_TRADE_PENDING, MT4_TRADE_PENDING_ACTIVE, MT4_TRADE_PENDING_UPDATE,
	MT4_TRADE_PENDING_DELETE, MT4_TRADE_UPDATE
};
struct WebSocketStreamHeader {
	unsigned int header_size;               //数据包头大小  
	int mask_offset;                    //掩码偏移  
	unsigned int payload_size;              //数据大小  
	bool fin;                                               //帧标记  
	bool masked;                            //掩码  
	unsigned char opcode;                   //操作码  
	unsigned char res[3];
};
enum WebSocketOpCode {
	ContinuationFrame = 0x0,                //连续帧  
	TextFrame = 0x1,                    //文本帧  
	BinaryFrame = 0x2,                  //二进制帧  
	ConnectionClose = 0x8,                  //连接关闭  
	Ping = 0x9,
	Pong = 0xA
};
struct USER_INFO
{
	CONNID dwConnID;
	std::string userid;
	std::string pwd;
	std::string symbols;
};
class TradeTransmit
  {
	
private:

 
  public:
	  TradeTransmit();
	  ~TradeTransmit();
   //--- initializing
   void					Initialize(void);
   int					Start();
   void					Stop();
   void					Out( LPCSTR msg, ...);
   void					SendMsg(std::string type, std::vector<json> desc, time_t open_time, time_t error_time, int error_code,std::string opr);

   void					DealTcpMsg();
   void					DealMt4Msg();
 
   int					ConnectPump(CManagerInterface *managerpump, const char* szIP, const int iUser, const char* szPassword);
   int					ConnectManager(CManagerInterface *manager, const char*  szIP, const int iUser, const char*  szPassword);
   void					ReConnectPump(CManagerInterface *manager, const char*  szIP, const int iUser, const char*  szPassword);
   void					DealFunEx(int code, int type, void * data);
   void					PumpHeart();
   void					AddMt4Msg(MT4_MSG * mt4_msg);
   bool					ReadMt4Msg(MT4_MSG & mt4_msg);
   void					DealTradeMsg(TradeRecord *trade,int type);
   void					DealUserMsg(UserRecord *user);
   void					DealRequestMsg(RequestInfo *info);
   void					DealMarginMsg(MarginLevel *ml);
   void					StampToGmt(int stampTime, std::string &datetime);
   static void __stdcall		PumpingFuncEx(int code, int type, void * data, void *param);
   std::vector<std::string> splitWithStl(const std::string &str, const std::string &pattern);
   char*				packData(const char * message, unsigned long * len, unsigned long n);
   bool					decodeRawData(const WebSocketStreamHeader& header, BYTE cbSrcData[], WORD wSrcLen, BYTE cbTagData[]);
   int					readHeader(const unsigned char* cData, WebSocketStreamHeader* header);
   std::string			base64Encode(unsigned char const* bytes_to_encode, unsigned int in_len);
   void					handShake(string inMessage, CONNID &dwConnID);
   void					checkUser(string inMessage, CONNID &dwConnID);
   void					deleteUser(CONNID dwConnID);
private:
	CManagerFactory   m_factory;
	CManagerInterface *m_pmanager;
	CManagerInterface *m_pmanager_pump;
	HANDLE				m_trade_event;
	std::mutex			m_trade_mutex;
	int					m_mt4_login;
	std::string			m_mt4_password;
	std::string			m_mt4_addr;
	std::deque<MT4_MSG>	m_trade_list;
	char				m_log_file[MAX_PATH];
	tools::logger		m_csv_record;

	bool				 m_run;
	tools::tim::timer	m_timer;
	std::thread		 m_deal_msg_thread;
	std::thread		 m_deal_mt4_thread;

	std::string			m_serveraddress;
	int					m_serverport;
	bool				m_server_update;
	std::string			m_master;
	char				m_groups[256];
	CTcpServerProcess	m_tcpserver;
	std::vector<std::string>	m_symbols;

	std::list<USER_INFO>	m_userList;
	std::list<USER_INFO>	m_userInfo;
  };

//+------------------------------------------------------------------+
