#pragma once

#include <string>
#include <map>

typedef void(__cdecl* TpyOrderOnConnected)(void*);
typedef void(__cdecl* TpyOrderOnDisconnected)(void*);
typedef void(__cdecl* TpyOrderOnLogonResponse)(void*, bool, const char*);
typedef void(__cdecl* TpyOrderOnReplyNewOrder)(void*, long long, const char*, const char*, double, const char*, long, const char*, const char*, const char*);
typedef void(__cdecl* TpyOrderOnReplyCancelOrder)(void*, long long, const char*, const char*, double, const char*, const char*);
typedef void(__cdecl* TpyOrderOnReplyReplaceOrder)(void*, long long, const char*, const char*, double, const char*, long, const char*, const char*, const char*);
typedef void(__cdecl* TpyOrderOnRejectOrder)(void*, long long, const char*, const char*, const char*, const char*);
typedef void(__cdecl* TpyOrderOnFill)(void*, long long, const char*, const char*, long, double, long, const char*);

 typedef void*       (*fptrPyOrderAdapter_New)();
 typedef void        (*fptrPyOrderAdapter_Delete)(void*);
 typedef bool        (*fptrPyOrderAdapter_IsConnected)(void*);
 typedef void        (*fptrPyOrderAdapter_Connect)(void*, const char*, int, int);
 typedef bool        (*fptrPyOrderAdapter_LogonProxy)(void*, const char*, const char*, const char*);
 typedef bool        (*fptrPyOrderAdapter_SetAccount)(void*, const char*, const char*, const char*);
 typedef void        (*fptrPyOrderAdapter_Disconnect)(void*);
 typedef long long   (*fptrPyOrderAdapter_SendNewForeignOrder)(void*, const char*, const char*, const char*, double, double, const char*, int, const char*, const char*, const char*, const char*);
 typedef long long   (*fptrPyOrderAdapter_SendNewOrderEx)(void*, const char*, const char*,	const char*, double, const char*, int, const char*, const char*, const char*, const char*, const char*);
 typedef long long   (*fptrPyOrderAdapter_SendCancelForeignOrder)(void*, const char*, const char*, const char*, const char*, const char*);
 typedef long long   (*fptrPyOrderAdapter_SendCancelOrderEx)(void*, const char*, const char*, const char*, double, const char*, const char*, const char*, const char*);
 typedef long long   (*fptrPyOrderAdapter_SendReplaceOrderEx)(void*, const char*, const char*, const char*, const char*, const char*, double, int, const char*, const char*, const char*, const char*);
 typedef void        (*fptrPyOrderAdapter_RegEvents)(void*, void*, TpyOrderOnConnected, TpyOrderOnDisconnected, TpyOrderOnLogonResponse, TpyOrderOnReplyNewOrder, TpyOrderOnReplyCancelOrder, TpyOrderOnReplyReplaceOrder, TpyOrderOnRejectOrder, TpyOrderOnFill);
 typedef const char* (*fptrPyOrderAdapter_GetLastErrorMessage)(void*);
 typedef bool        (*fptrPyOrderAdapter_EnableMegaCA)(void*, const char*, const char*, const char*);
 typedef void*       (*fptrPyOrderAdapter_CreateQueryParam)();
 typedef void        (*fptrPyOrderAdapter_FreeQueryParam)(void*);
 typedef void        (*fptrPyOrderAdapter_AddQueryParam)(void*, const char*, const char*);
 typedef const char* (*fptrPyOrderAdapter_GetStringFromQueryResult)(void*, int);
 typedef void        (*fptrPyOrderAdapter_FreeQueryResult)(void*);
 typedef void*       (*fptrPyOrderAdapter_ChangePassword)(void*, void*);
 typedef void*       (*fptrPyOrderAdapter_MakeStockAccountInquriy)(void*, void*);
 typedef void*       (*fptrPyOrderAdapter_QueryStkOrder)(void*, void*);
 typedef void*       (*fptrPyOrderAdapter_QueryStkMatch)(void*, void*);
 typedef void*       (*fptrPyOrderAdapter_QueryFutOrder)(void*, void*);
 typedef void*       (*fptrPyOrderAdapter_QueryFutMatch)(void*, void*);
 typedef void*       (*fptrPyOrderAdapter_QueryFutUncoverRT)(void*, void*);
 typedef void*       (*fptrPyOrderAdapter_QueryMargin)(void*, void*);
 typedef void*       (*fptrpyOrderAdapter_QueryForeignStockInventory)(void*, void*);
 typedef void*       (*fptrpyOrderAdapter_QueryForeignStockOrder)(void*, void*);
 typedef void*       (*fptrpyOrderAdapter_QueryForeignStockFilled)(void*, void*);
 typedef void*       (*fptrpyOrderAdapter_DownloadForeignStockProductData)(void*, void*, const char*);
 typedef void*       (*fptrpyOrderAdapter_DownloadForeignStockCurrencyData)(void*, void*);
 typedef void*       (*fptrpyOrderAdapter_DownloadForeignStockMarketData)(void*, void*);
 typedef void*       (*fptrpyOrderAdapter_GetMKChartData)(void* , const char*);
 typedef void*       (*fptrpyOrderAdapter_GetWKChartData)(void* , const char*);
 typedef void*       (*fptrpyOrderAdapter_GetDKChartData)(void* , const char*);
 typedef void*       (*fptrpyOrderAdapter_GetAdjustedDKChartData)(void* , const char*);
 typedef void*       (*fptrpyOrderAdapter_GetAdjustedWKChartData)(void* , const char*);
 typedef void*       (*fptrpyOrderAdapter_GetAdjustedMKChartData)(void* , const char*);

 class spdOrderAPI
 {
 private:
	 void* orderAPI;

 private:
	 static bool LoadOrderAPIFromDLL();
	 static void OnOrderConnected(void* user_defined);
	 static void OnOrderDisconnected(void* user_defined);
	 static void OnOrderLogonResponse(void* user_defined, bool isLoginOK, const char* ReplyMsg);
	 static void OnReplyNewOrder(void* user_defined, long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, long OrderQty, const char* OrderType, const char* TimeinForce, const char* OrderID);
	 static void OnReplyCancelOrder(void* user_defined, long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, const char* OrderID);
	 static void OnReplyReplaceOrder(void* user_defined, long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, long OrderQty, const char* OrderType, const char* TimeinForce, const char* OrderID);
	 static void OnOrderRejected(void* user_defined, long long nid, const char* UDD, const char* ActionFrom, const char* ErrCode, const char* ErrMsg);
	 static void OnOrderFilled(void* user_defined, long long nid, const char* UDD, const char* OrderID, long ReportSeq, double MatchPrice, long MatchQty, const char* MatchTime);

 protected:
	 virtual void OnSpeedyConnected() {}
	 virtual void OnSpeedyDisconnected() {}
	 virtual void OnSpeedyLogonResponse(bool isLoginOK, const char* ReplyMsg) {}
	 virtual void OnNewOrderReport(long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, long OrderQty, const char* OrderType, const char* TimeinForce, const char* OrderID) {}
	 virtual void OnCancelOrderReport(long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, const char* OrderID) {}
	 virtual void OnReplaceOrderReport(long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, long OrderQty, const char* OrderType, const char* TimeinForce, const char* OrderID) {}
	 virtual void OnOrderRejectedReport(long long nid, const char* UDD, const char* ActionFrom, const char* ErrCode, const char* ErrMsg) {}
	 virtual void OnOrderMatchReport(long long nid, const char* UDD, const char* OrderID, long ReportSeq, double MatchPrice, long MatchQty, const char* MatchTime) {}

 public:
	 spdOrderAPI();
	 virtual ~spdOrderAPI();

	 bool IsSpeedyConnected(void);
	 void ConnectSpeedy(const char* IP, int Port, int TimeoutSec);
	 bool LogonSpeedy(const char* ID, const char* Password, const char* Account);
	 bool SetAccount(const char* Exchange, const char* BrokerID, const char* Account);
	 void DisconnectSpeedy(void);

	 long long SendNewOrder(const char* Market,
		                    const char* UDD,
		                    const char* Symbol,
		                    double      Price,
		                    const char* Side,
		                    int         OrderQty,
		                    const char* OrderType,
		                    const char* TimeInForce,
		                    const char* TradingSession,
		                    const char* PositionEffect,
		                    const char* TWSEOrdType);

	 long long SendNewForeignOrder(const char* Exchange,
		                           const char* UDD,
		                           const char* Symbol,
		                           double      Price,
		                           double      StopPrice,
		                           const char* Side,
		                           int         OrderQty,
		                           const char* OrderType,
		                           const char* TimeInForce,
		                           const char* Currency,
		                           const char* ExecInst);

	 long long SendCancelOrder(const char* Market,
		                       const char* UDD,
		                       const char* Symbol,
		                       double      Price,
		                       const char* Side,
		                       const char* OrderID,
		                       const char* TradingSession,
		                       const char* TWSEOrdType);

	 long long SendCancelForeignOrder(const char* Exchange,
		                              const char* UDD,
		                              const char* Symbol,
		                              const char* Side,
		                              const char* OrderID);

	 long long SendReplaceOrder(const char* Market,
		                        const char* UDD,
		                        const char* Symbol,
		                        const char* OrderID,
		                        const char* Side,
		                        double      Price,
		                        int         OrderQty,
		                        const char* OrderType,
		                        const char* TimeInForce,
		                        const char* TradingSession,
		                        const char* TWSEOrdType);
	 	 
	 std::string GetOrderAPILastErrorMessage();
	 bool EnableMegaCA(const char* pfx_path, const char* pfx_id, const char* pfx_pwd);
	 std::string ChangePassword(const std::map<std::string, std::string>& query_param);
	 std::string MakeStockAccountInquriy(const std::map<std::string, std::string>& query_param);
	 std::string QueryStkOrder(const std::map<std::string, std::string>& query_param);
	 std::string QueryStkMatch(const std::map<std::string, std::string>& query_param);
	 std::string QueryFutOrder(const std::map<std::string, std::string>& query_param);
	 std::string QueryFutMatch(const std::map<std::string, std::string>& query_param);
	 std::string QueryFutUncoverRT(const std::map<std::string, std::string>& query_param);
	 std::string QueryMargin(const std::map<std::string, std::string>& query_param);
	 std::string QueryForeignStockInventory(const std::map<std::string, std::string>& query_param);
	 std::string QueryForeignStockOrder(const std::map<std::string, std::string>& query_param);
	 std::string QueryForeignStockFilled(const std::map<std::string, std::string>& query_param);
	 std::string DownloadForeignStockProductData(const std::map<std::string, std::string>& query_param, const char* gzfname_prefix);
	 std::string DownloadForeignStockCurrencyData(const std::map<std::string, std::string>& query_param);
	 std::string DownloadForeignStockMarketData(const std::map<std::string, std::string>& query_param);
	 std::string GetMKChartData(const char* symbol);
	 std::string GetWKChartData(const char* symbol);
	 std::string GetDKChartData(const char* symbol);
	 std::string GetAdjustedDKChartData(const char* symbol);
	 std::string GetAdjustedWKChartData(const char* symbol);
	 std::string GetAdjustedMKChartData(const char* symbol);
 };
 