#pragma once

#include <atomic>
#include <cstdint>

#include "xlt_quote_api.h"
#include "efh_quote_decoder.h"
#include "xlt_quote_decoder.h"


using namespace x1;
/**
 * @brief XLTQuoteApi Demo
 * 本类演示了如何使用XLTQuoteApi进行行情相关的操作，包括API初始化、登录、查询行情信息等。
 * 用户可以参考本类中的方法，根据实际业务场景进行调整和扩展。
 */
class XLTQuoteDemo : public XLTQuoteSpi{
public:
    XLTQuoteDemo();
    ~XLTQuoteDemo() override = default;

    XLTQuoteDemo(const XLTQuoteDemo&) = delete;
    XLTQuoteDemo& operator=(const XLTQuoteDemo&) = delete;

    const char* api_version() const;
    uint32_t trading_day() const;

    /**
     * @brief 【演示】获取下一个请求ID
     * XLTApi中使用request_id用于用户在异步回调中定位对应的请求。
     * XLTApi所有接口使用到request_id时，不对request_id做任何验证及业务假设，在回调中原样返回给用户。
     * 此方法用于演示request_id，用户可根据实际业务场景，自定义request_id。
     * @return 下一个请求ID
     */
    uint64_t next_request_id();

    /**
     * @brief 【演示】XLTQuoteApi初始化
     *
     * 本方法演示如何配置以及初始化API，步骤如下：
     * 1、配置API
     * 2、初始化：设置行情API配置，以及注册交易回调接口和行情回调接口
     * @return 初始化是否成功
     * @remark XLTQuoteApi必须在使用之前进行初始化，并且只能初始化一次
     */
    bool initialize();

    /**
     * @brief 【演示】登录请求
     * 本方法演示XLTQuoteApi登录过程
     * XLTQuoteApi登录响应为异步响应，本方法封装为同步过程，用户根据实际业务场景进行调整。
     * 流程如下：
     * 1、发起登录请求
     * 2、等待异步响应
     * 3、判断是否登录成功，若成功，保存会话ID global_quote_session_id
     * 后续接口调用都需要用到本次登录返回的global_quote_session_id
     * @return 登录是否成功
     * @remark 登录时，用户可自定义client_id，在本次登录中的所有委托及回报都将打上此标记，用于用户进行委托隔离
     */
    bool login();

    /**
     * @brief 【演示】订阅行情
     * 本方法演示如何订阅行情
     * @return 订阅是否成功
     */
    bool subscribe_quote();

    /**
     * @brief 【演示】查询静态行情信息
     * 本方法演示如何查询静态行情信息
     * 结果将从on_query_static_quote_info回调中返回
     * @return 查询请求发送是否成功
     */
    bool query_static_quote_info();

    /**
     * @brief 【演示】查询单个证券level1行情
     * 本方法演示如何查询指定市场和证券代码的level1行情
     * 结果将从on_query_level1_quote回调中返回
     * @param exchange_index 交易所代码
     * @param security_code 证券代码
     * @return 查询请求发送是否成功
     */
    bool query_level1_quote(x1::ExchangeIndex exchange_index, const char* security_code);

    /**
     * @brief 【演示】查询全量level1行情
     * 本方法演示如何查询全量level1行情数据
     * 结果将从on_query_all_level1_quote回调中返回，可能分多条消息返回
     * @return 查询请求发送是否成功
     */
    bool query_all_level1_quote();

    /**
     * @brief 【演示】请求回补逐笔行情
     * 本方法演示如何请求回补指定通道、指定序号范围的逐笔行情数据
     * 请求结果将从on_request_rebuild_tick_quote回调中返回
     * 回补的逐笔数据将从on_rebuild_tick_quote回调中推送
     * @param exchange_index 交易所代码
     * @param channel_no 频道代码
     * @param begin_sequence 起始消息记录号
     * @param end_sequence 结束消息记录号
     * @return 请求发送是否成功
     */
    bool request_rebuild_tick_quote(x1::ExchangeIndex exchange_index, int16_t channel_no, int64_t begin_sequence, int64_t end_sequence);

    // ---------------- XLTQuoteSpi 回调 ----------------
    void on_disconnect(uint64_t session_id) override;
    void on_login(uint64_t session_id, uint64_t request_id, const x1::xlt_error_info_t* error_info) override;

    void on_query_static_quote_info(uint64_t session_id, uint64_t request_id, const x1::XLTStaticQuoteList* static_quotes,
                                    bool is_last, const x1::xlt_error_info_t* error_info) override;

    void on_query_level1_quote(uint64_t session_id, uint64_t request_id, const x1::xlt_level1_quote_t* level1_quote,
                               const x1::xlt_error_info_t* error_info) override;

    void on_query_all_level1_quote(uint64_t session_id, uint64_t request_id, const x1::XLTLevel1QuoteList* level1_quotes,
                                   bool is_last, const x1::xlt_error_info_t* error_info) override;

    void on_quote(x1::QuoteMCType mc_type, const void* msg_data, uint32_t msg_len) override;

    void on_request_rebuild_tick_quote_error(uint64_t session_id, uint64_t request_id, const x1::xlt_error_info_t* error_info) override;

    void on_rebuild_tick_quote(uint64_t session_id, uint64_t request_id, x1::ExchangeIndex exchange_index, x1::QuoteMsgType msg_type, const x1::xlt_tick_quote_union_t* tick_quote) override;

    // ----用户自定义消息处理----
    void on_report_efh_sse_lev2_snap(const sse_hpf_lev2* p_snap);
    void on_report_efh_sse_lev2_tick_merge(const sse_hpf_tick_merge* p_tick);
    void on_report_efh_sse_lev2_idx(const sse_hpf_idx* p_idx);
    void on_report_efh_sse_lev2_bond_snap(const sse_hpf_bond_snap* p_bond_snap);
    void on_report_efh_sse_lev2_bond_tick(const sse_hpf_bond_tick* p_bond_tick);
    void on_report_efh_sze_lev2_snap(const sze_hpf_lev2* p_snap);
    void on_report_efh_sze_lev2_tick(int msg_type, const sze_hpf_order* p_order, const sze_hpf_exe* p_exe);
    void on_report_efh_sze_lev2_idx(const sze_hpf_idx* p_idx);
    void on_report_efh_sze_lev2_bond_snap(const sze_hpf_bond_snap* p_bond_snap);
    void on_report_efh_sze_lev2_bond_tick(int msg_type, const sze_hpf_bond_order* p_order,
        const sze_hpf_bond_exe* p_exe);

    void on_sse_l1_index(const xlt_sse_l1_index_t* sse_l1_index);
    void on_sse_l1_snapshot(const xlt_sse_l1_snapshot_t* sse_l1_snapshot);
    void on_szse_l1_index(const xlt_szse_l1_index_t* szse_l1_index);
    void on_szse_l1_snapshot(const xlt_szse_l1_snapshot_t* szse_l1_snapshot);
    void on_szse_l1_snapshot_bond(const xlt_szse_l1_snapshot_bond_t* szse_l1_snapshot_bond);

    void print_level1_quote(const xlt_level1_quote_t* level1_quote);

private:
    x1::XLTQuoteApi* api_{nullptr};

    uint64_t session_id_{0};
    std::atomic<bool> login_success_{false};
    std::atomic<bool> login_finished_{false};
    std::atomic<uint64_t> request_id_{0};

};

