#pragma once

#include "xlt_trade_api.h"
#include "xlt_privilege_struct.h"
#include "xlt_privilege_config.h"
#include "xlt_privilege_list.h"

namespace x1 {
    /**
     * @brief 管理接口回调类
     */
    class XLTPrivilegeSpi : public XLTTradeSpi {
    public:
        ~XLTPrivilegeSpi() override = default;

        /**
         * @brief token信息推送
         * @param session_id 会话ID。
         * @param msg_desc 消息描述信息
         * @param token token信息
         */
        virtual void on_token(uint64_t session_id, const xlt_msg_desc_t* msg_desc, const xlt_internal_token_info_t* token) {};

        /**
         * @brief 行情登录信息推送
         * @param session_id 会话ID。
         * @param msg_desc 消息描述信息
         * @param quote_login_info 行情登录记录
         */
        virtual void on_quote_login_info(uint64_t session_id, const xlt_msg_desc_t* msg_desc, const xlt_internal_quote_login_info_t* quote_login_info) {};
        /**
         * @brief 资金划转执行结果回调
         * subscribe_trade_message或rebuild_trade_message指定任意消息类型时，交易系统会在账户资金发生变动时推送该通知。
         * @param session_id 会话ID
         * @param msg_desc 消息描述信息
         * @param fund_transfer_exec_result 资金划转执行结果
         */
        virtual void on_fund_transfer_exec_result(uint64_t session_id, const xlt_msg_desc_t* msg_desc, const xlt_fund_transfer_exec_result_t* fund_transfer_exec_result) {};
        /**
         * @brief 导出下场文件响应
         * @param session_id 会话id，登录时得到
         * @param request_id 此消息响应函数对应的请求ID
         * @param success 导出是否成功
         * @param error_info 查询发生错误时，返回的错误信息，当error_info为空，或者error_info.error_id为0时，表明没有错误
         */
        virtual void on_dump_final_file(uint64_t session_id, uint64_t request_id, bool success, const xlt_error_info_t* error_info) {};

        /**
         * @brief 解绑用户与交易网关的绑定关系响应
         * @param session_id 会话id，登录时得到
         * @param request_id 此消息响应函数对应的请求ID
         * @param account_index 账号索引
         * @param error_info 发生错误时，返回的错误信息，当error_info为空，或者error_info.error_id为0时，表明没有错误
         */
        virtual void on_unbind_user_tgw(uint64_t session_id, uint64_t request_id, uint64_t account_index, const xlt_error_info_t* error_info) {};
        /**
         * @brief 简要资产查询响应
         * @param session_id 会话id，登录时得到
         * @param request_id 此消息响应函数对应的请求ID
         * @param brief_assets 查询到的简要资产信息列表
         * @param is_last 此消息响应函数是否为request_id这条请求所对应的最后一个响应，当为最后一个的时候为true，如果为false，表示还有其他后续消息响应
         * @param error_info 查询发生错误时，返回的错误信息，当error_info为空，或者error_info.error_id为0时，表明没有错误
         */
        virtual void on_query_brief_assets(uint64_t session_id, uint64_t request_id, const XLTBriefAssetList* brief_assets, bool is_last, const xlt_error_info_t* error_info) {};
        /**
         * @brief 简要持仓查询响应
         * @param session_id 会话id，登录时得到
         * @param request_id 此消息响应函数对应的请求ID
         * @param brief_positions 查询到的简要持仓信息列表
         * @param is_last 此消息响应函数是否为request_id这条请求所对应的最后一个响应，当为最后一个的时候为true，如果为false，表示还有其他后续消息响应
         * @param error_info 查询发生错误时，返回的错误信息，当error_info为空，或者error_info.error_id为0时，表明没有错误
         */
        virtual void on_query_brief_positions(uint64_t session_id, uint64_t request_id, const XLTBriefPositionList* brief_positions, bool is_last, const xlt_error_info_t* error_info) {};
    };


    /**
     * @brief 管理接口类
     */
    class XLTPrivilege: public XLTTradeApi {
    public:
        /**
         * @brief 创建实例（只能创建一次）
         * @return 返回管理接口实例
         */
        static XLTPrivilege* create();
        /**
         * @brief 根据订单ID获取token_id
         * @param xid
         * @return token_id
         */
        static uint64_t xid_to_token_id(uint64_t xid);
        /**
         * @brief 初始化API，登录之前必须调用此函数，只能初始化一次
         * @param config 配置信息
         * @param spi 回调接口
         * @return 初始化是否成功
         */
        bool initialize(XLTPrivilegeConfig* config, XLTPrivilegeSpi* spi);
        /**
         * @brief 停止特权API
         * 断开所有特权session连接，清空所有session上的回调指针，停止回调。
         * @remark 调用stop后，所有未完成的回调将不再触发，用户可安全地释放对象。
         */
        void stop();
        /**
         * @brief 用户登录请求
         * @param request_id 用于用户定位请求响应的ID，由用户自定义
         * @param account_name 交易账号
         * @param password 登录密码
         * @param pub_key 用户公钥(长度64字节)，系统分发
         * @return 查询请求发送是否成功，若失败时用户可以调用get_last_error()来获取错误信息。
         */
        bool login(uint64_t request_id, const char* account_name, const char* password, const char* pub_key);
        /**
         * @brief 导出下场文件
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位查询响应的ID，由用户自定义
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误代码
         */
        bool dump_final_file(uint64_t session_id, uint64_t request_id);
        /**
         * @brief 解绑用户与交易网关的绑定关系
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位查询响应的ID，由用户自定义
         * @param account_index 账号索引
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误代码
         */
        bool unbind_user_tgw(uint64_t session_id, uint64_t request_id, uint64_t account_index);
        /**
         * @brief 插入资金划转执行请求
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位响应的ID，由用户自定义
         * @param fund_transfer_exec_req 资金划转执行请求信息
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误代码
         */
        bool insert_fund_transfer_exec(uint64_t session_id, uint64_t request_id, const xlt_fund_transfer_exec_request_t* fund_transfer_exec_req);
        /**
         * @brief 提交资金划转请求
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位响应的ID，由用户自定义
         * @param fund_transfer_request 资金划转请求信息
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误代码
         */
        bool submit_counter_fund_transfer_request(uint64_t session_id, uint64_t request_id, const xlt_counter_fund_transfer_request_t* fund_transfer_request);
        /**
         * @brief 提交资金划转结果
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位响应的ID，由用户自定义
         * @param fund_transfer_result 资金划转结果信息
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误代码
         */
        bool submit_counter_fund_transfer_result(uint64_t session_id, uint64_t request_id, const xlt_counter_fund_transfer_result_t* fund_transfer_result);
        /**
         * @brief 提交双中心资金划转请求
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位响应的ID，由用户自定义
         * @param cluster_fund_transfer_request 双中心资金划转请求信息
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误代码
         */
        bool submit_cluster_fund_transfer_request(uint64_t session_id, uint64_t request_id, const xlt_cluster_fund_transfer_request_t* cluster_fund_transfer_request);
        /**
         * @brief 提交双中心资金划转结果
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位响应的ID，由用户自定义
         * @param cluster_fund_transfer_result 双中心资金划转结果信息
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误代码
         */
        bool submit_cluster_fund_transfer_result(uint64_t session_id, uint64_t request_id, const xlt_cluster_fund_transfer_result_t* cluster_fund_transfer_result);
        /**
         * @brief 请求查询简要资产信息
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位查询响应的ID，由用户自定义
         * @param account_index 交易账号索引
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误信息。
         */
        bool query_brief_assets(uint64_t session_id, uint64_t request_id, uint64_t account_index = 0);
        /**
         * @brief 请求查询简要持仓信息
         * @param session_id 会话id，登录时得到
         * @param request_id 用于用户定位查询响应的ID，由用户自定义
         * @param security_code 需要查询持仓的合约代码，可以为空表示查询全市场，如果不为空，请不带空格，并以'\0'结尾
         * @param exchange_index 需要查询持仓的合约所在市场，默认为INIT。如果想正确查询指定持仓，请指定exchange_index
         * @param account_index 交易账号索引
         * @return 请求发送是否成功，true表示成功，false表示出错，此时用户可以调用get_last_error()来获取错误信息。
         * @remark 该方法如果用户提供了合约代码，则会查询此合约的持仓信息，如果合约代码为空，则默认查询所有持仓信息。
         */
        bool query_brief_positions(uint64_t session_id, uint64_t request_id, const char* security_code, ExchangeIndex exchange_index, uint64_t account_index = 0);
    private:
        XLTPrivilege() = default;
    };
}
