#pragma once

#include <cstddef>
#include <cstdint>

#ifdef XYPARSER_EXPORTS
#define XYPARSER_API __declspec(dllexport)
#else
#define XYPARSER_API __declspec(dllimport)
#endif

extern "C" {

typedef void* XYParserHandle;

enum {
    XYPARSER_MAX_CHANNELS = 64,
    XYPARSER_FRAME_DATA_TRIGGER_TYPE_INDEX = XYPARSER_MAX_CHANNELS,
    XYPARSER_FRAME_DATA_TRIGGER_INDEX_INDEX = XYPARSER_MAX_CHANNELS + 1,
    XYPARSER_FRAME_DATA_COLUMN_COUNT = XYPARSER_MAX_CHANNELS + 2,
    XYPARSER_SAMPLES_PER_FRAME = 5,
    XYPARSER_FRAME_ALGORITHM_VALUE_COUNT =
        XYPARSER_SAMPLES_PER_FRAME * XYPARSER_FRAME_DATA_COLUMN_COUNT,
    XYPARSER_WELCH_MAX_FREQUENCY_COUNT = 50,
    XYPARSER_WELCH_BAND_COUNT = 5
};

enum XYParser8ChImpedanceSwitch : std::uint8_t {
    XYPARSER_8CH_IMPEDANCE_CLOSE = 0xA0,
    XYPARSER_8CH_IMPEDANCE_OPEN = 0xA1
};

enum XYParserTriggerType : std::uint8_t {
    XYPARSER_TRIGGER_NONE = 0x00,
    XYPARSER_TRIGGER_TRAIN_0 = 0xBB,
    XYPARSER_TRIGGER_TRAIN_1 = 0xBC
};

enum XYParserLeadChannelNumber {
    LeadChannel_FP1 = 0,
    LeadChannel_FP2,
    LeadChannel_PO6,
    LeadChannel_POZ,
    LeadChannel_F3,
    LeadChannel_F4,
    LeadChannel_FPZ,
    LeadChannel_AF4,
    LeadChannel_FC3,
    LeadChannel_PO8,
    LeadChannel_CP2,
    LeadChannel_CP1,
    LeadChannel_FCZ,
    LeadChannel_PO5,
    LeadChannel_FC2,
    LeadChannel_FC1,
    LeadChannel_C3,
    LeadChannel_C4,
    LeadChannel_FC4,
    LeadChannel_CP4,
    LeadChannel_P3,
    LeadChannel_P4,
    LeadChannel_F5,
    LeadChannel_C5,
    LeadChannel_F6,
    LeadChannel_PO4,
    LeadChannel_CP6,
    LeadChannel_CP5,
    LeadChannel_PO3,
    LeadChannel_CP3,
    LeadChannel_FC6,
    LeadChannel_FC5,
    LeadChannel_CB1,
    LeadChannel_CB2,
    LeadChannel_P5,
    LeadChannel_AF7,
    LeadChannel_A1,
    LeadChannel_T7,
    LeadChannel_FT7,
    LeadChannel_TP7,
    LeadChannel_FT8,
    LeadChannel_AF8,
    LeadChannel_F8,
    LeadChannel_F7,
    LeadChannel_P6,
    LeadChannel_C6,
    LeadChannel_O2,
    LeadChannel_O1,
    LeadChannel_T8,
    LeadChannel_P7,
    LeadChannel_CZ,
    LeadChannel_PZ,
    LeadChannel_P8,
    LeadChannel_FZ,
    LeadChannel_OZ,
    LeadChannel_PO7,
    LeadChannel_TP8,
    LeadChannel_AF3,
    LeadChannel_C2,
    LeadChannel_C1,
    LeadChannel_P2,
    LeadChannel_P1,
    LeadChannel_F2,
    LeadChannel_F1,
    LeadChannel_GND
};

struct XYParserFrameSummary {
    std::uint32_t frame_index;
    std::uint8_t channel_count;
    std::uint8_t battery;
    std::uint8_t sample_count;
    // 0=正常采集，1=阻抗检测中。
    std::uint8_t impedance_enabled;
    // 当前设备增益值，例如 1/2/3/4/6/8/12/24。
    std::uint8_t current_gain;
    // 当前实际采样率（Hz），例如 250/500/1000/2000，不是协议枚举值。
    std::uint16_t current_sample_rate_hz;
    // 当前脑电帽类型，保留设备上报的原始值。
    std::uint8_t cap_type;
    // GND 脱落状态，0=正常，1=脱落。
    std::uint8_t gnd_detached;
    double channel_values_uv[XYPARSER_SAMPLES_PER_FRAME][XYPARSER_MAX_CHANNELS];
    std::uint8_t sample_trigger_types[XYPARSER_SAMPLES_PER_FRAME];
    std::uint8_t sample_trigger_indices[XYPARSER_SAMPLES_PER_FRAME];
};

struct XYParserImpedanceSummary {
    std::uint8_t channel_count;
    std::uint32_t sample_rate;
    std::uint32_t window_sample_count;
    std::uint16_t impedance_values[XYPARSER_MAX_CHANNELS];
};

struct XYParserWelchSummary {
    std::uint8_t ok;
    std::uint8_t channel_count;
    std::uint32_t sample_rate;
    std::uint32_t window_sample_count;
    std::uint32_t frequency_count;
    double frequencies[XYPARSER_WELCH_MAX_FREQUENCY_COUNT];
    double psd_values[XYPARSER_MAX_CHANNELS][XYPARSER_WELCH_MAX_FREQUENCY_COUNT];
    double band_values[XYPARSER_WELCH_BAND_COUNT][XYPARSER_MAX_CHANNELS];
};

// 创建解析器实例。
// @param channel_count 解析器支持的导联数。
// @return 创建成功时返回解析器句柄，失败时返回 nullptr。
XYPARSER_API XYParserHandle XYParser_CreateParser(std::uint8_t channel_count);

// 销毁解析器实例并释放相关资源。
// @param handle 要销毁的解析器句柄。
// @return 无返回值。
XYPARSER_API void XYParser_DestroyParser(XYParserHandle handle);

// 设置 ADC 参考电压和增益参数。
// @param handle 目标解析器句柄。
// @param vref ADC 的参考电压。
// @param gain ADC 的增益值。
// @return 无返回值。
XYPARSER_API void XYParser_SetAdcParams(XYParserHandle handle, double vref, double gain);

// 设置是否跳过校验和检查。
// @param handle 目标解析器句柄。
// @param bypass 非 0 表示跳过校验和检查，0 表示执行校验和检查。
// @return 无返回值。
XYPARSER_API void XYParser_SetBypassChecksum(XYParserHandle handle, int bypass);

// 设置解析器使用的采样率。
// @param handle 目标解析器句柄。
// @param sample_rate 采样率，单位为 Hz。
// @return 无返回值。
XYPARSER_API void XYParser_SetSampleRate(XYParserHandle handle, int sample_rate);

// Frame parsing and algorithm result reading.
// 向解析器输入原始数据并读取解析得到的帧。
// @param handle 目标解析器句柄。
// @param data 输入的原始字节数据。
// @param size 输入数据的字节数。
// @param out_summaries 输出帧数组。
// @param max_summaries 输出数组可写入的最大帧数，用于避免越界写入。
// @return 本次实际输出的帧数；如果参数无效则返回 0。
XYPARSER_API int XYParser_Feed(XYParserHandle handle,
                               const std::uint8_t* data,
                               std::size_t size,
                               XYParserFrameSummary* out_summaries,
                               int max_summaries);

// 设置是否启用阻抗检测。
// @param handle 目标解析器句柄。
// @param enabled 非 0 表示启用阻抗检测，0 表示禁用阻抗检测。
// @return 无返回值。
XYPARSER_API void XYParser_SetImpedanceDetection(XYParserHandle handle, int enabled);

// 读取当前可用的阻抗结果。
// @param handle 目标解析器句柄。
// @param out_summaries 输出的阻抗结果数组。
// @param max_summaries 输出数组可写入的最大结果数，用于避免越界写入。
// @return 本次实际读取的结果数；如果参数无效则返回 0。
XYPARSER_API int XYParser_ReadImpedance(XYParserHandle handle,
                                        XYParserImpedanceSummary* out_summaries,
                                        int max_summaries);

// 设置是否启用基于算法数据的 Welch 检测。
// @param handle 目标解析器句柄。
// @param enabled 非 0 表示启用 Welch 检测，0 表示禁用 Welch 检测。
// @return 无返回值。
XYPARSER_API void XYParser_SetWelchDetection(XYParserHandle handle, int enabled);

// 读取当前基于算法数据计算得到的 Welch 结果。
// @param handle 目标解析器句柄。
// @param out_summaries 输出的 Welch 结果数组。
// @param max_summaries 输出数组可写入的最大结果数，用于避免越界写入。
// @return 本次实际读取的结果数；如果参数无效则返回 0。
XYPARSER_API int XYParser_ReadWelch(XYParserHandle handle,
                                    XYParserWelchSummary* out_summaries,
                                    int max_summaries);

// Command serialization.
// 获取 8 导阻抗命令的字节长度。
// @return 8 导阻抗命令的字节长度。
XYPARSER_API std::size_t XYParser_Get8ChImpedanceCommandSize();

// 生成 8 导阻抗开关命令。
// @param open 非 0 表示打开阻抗检测，0 表示关闭阻抗检测。
// @param out_command 输出的命令缓冲区。
// @param command_size 输出缓冲区大小，单位为字节。
// @return 生成成功时返回写入的字节数，失败时返回 0。
XYPARSER_API int XYParser_Serialize8ChImpedanceCommand(int open,
                                                       std::uint8_t* out_command,
                                                       std::size_t command_size);

// Get trigger command size.
// @return Size in bytes of the trigger command.
XYPARSER_API std::size_t XYParser_GetTriggerCommandSize(void);

// Serialize a trigger command.
// Packet layout matches sendCmd(): 0xAA + TriggerEventStruct payload + checksum(payload) + 0x55 + 0x55.
// Current payload layout follows WirelessEEG TriggerEventStruct: 2 reserved bytes + 1 trigger byte.
// @param trigger_type Trigger code to send. Prefer values from XYParserTriggerType.
// @param out_command Output buffer for serialized bytes.
// @param command_size Size of output buffer in bytes.
// @return Number of bytes written on success, or 0 on failure.
XYPARSER_API int XYParser_SerializeTriggerCommand(std::uint8_t trigger_type,
                                                  std::uint8_t* out_command,
                                                  std::size_t command_size);

// 获取 64 导阻抗命令的字节长度。
// @return 64 导阻抗命令的字节长度。
XYPARSER_API std::size_t XYParser_Get64ImpedanceCommandSize(void);

// 生成 64 导阻抗开关命令。
// @param open 非 0 表示打开阻抗检测，0 表示关闭阻抗检测。
// @param out_buffer 输出的命令缓冲区。
// @param buffer_size 输出缓冲区大小，单位为字节。
// @return 生成成功时返回写入的字节数，失败时返回 0。
XYPARSER_API int XYParser_Serialize64ImpedanceCommand(int open,
                                                      std::uint8_t* out_buffer,
                                                      std::size_t buffer_size);

// 获取 64 导增益和采样率命令的字节长度。
// @return 64 导增益和采样率命令的字节长度。
XYPARSER_API std::size_t XYParser_Get64GainSampleRateCommandSize(void);

// 生成 64 导增益和采样率设置命令。
// @param gain 要设置的增益值。
// @param sample_rate 要设置的采样率。
// @param out_buffer 输出的命令缓冲区。
// @param buffer_size 输出缓冲区大小，单位为字节。
// @return 生成成功时返回写入的字节数，失败时返回 0。
XYPARSER_API int XYParser_Serialize64GainSampleRateCommand(std::uint8_t gain,
                                                           std::uint16_t sample_rate,
                                                           std::uint8_t* out_buffer,
                                                           std::size_t buffer_size);

// Frame conversion and algorithm data output.
// 将 8 导帧批量转换为 64 导帧，未映射的导联补 0。
// @param input_summaries 输入的 8 导帧数组。
// @param input_count 输入数组中的帧数。
// @param output_summaries 输出的 64 导帧数组。
// @param max_summaries 输出数组可写入的最大帧数，用于避免越界写入。
// @return 实际成功转换的帧数；如果参数无效则返回 0，如果中途遇到非 8 导帧则返回已完成转换的数量。
XYPARSER_API int XYParser_Convert8ChFramesTo64Ch(const XYParserFrameSummary* input_summaries,
                                                 int input_count,
                                                 XYParserFrameSummary* output_summaries,
                                                 int max_summaries);

// 获取算法数据数组所需的元素数量。
// @return 算法数据数组所需的元素数量。
XYPARSER_API std::size_t XYParser_GetAlgorithmDataValueCount();

// 将单帧数据转换为算法接口使用的连续数组。
// @param input_summary 输入的单帧数据。
// @param output_data 输出的算法数据数组。
// @return 转换成功时返回非 0，失败时返回 0。
XYPARSER_API int XYParser_ConvertSampleFramesToAlgorithmData(const XYParserFrameSummary* input_summary,
                                                             double* output_data);

// 向算法数据缓存输入字节流，并按每 5 个采样组装为帧，同时驱动 Welch 计算。
// @param handle 目标解析器句柄。
// @param data 输入的算法数据字节流。
// @param size 输入数据的字节数。
// @param out_summaries 输出的帧数组。
// @param max_summaries 输出数组可写入的最大帧数，用于避免越界写入。
// @return 实际输出的帧数；如果参数无效则返回 0。
XYPARSER_API int XYParser_FeedAlgorithmData(XYParserHandle handle,
                                            const std::uint8_t* data,
                                            std::size_t size,
                                            XYParserFrameSummary* out_summaries,
                                            int max_summaries);

// 清空算法数据缓存。
// @param handle 目标解析器句柄。
// @return 无返回值。
XYPARSER_API void XYParser_ResetAlgorithmDataCache(XYParserHandle handle);

// 将缓存中不足 5 个采样的尾数据补齐并输出为 1 帧。
// @param handle 目标解析器句柄。
// @param out_summary 输出的帧。
// @return 成功输出 1 帧时返回 1；没有可输出的数据或参数无效时返回 0。
XYPARSER_API int XYParser_FlushAlgorithmData(XYParserHandle handle,
                                             XYParserFrameSummary* out_summary);

// Lead and Welch metadata.
// 获取指定导联数对应的导联映射数量。
// @param channel_count 导联数。
// @return 导联映射数量；如果导联数不支持则返回 0。
XYPARSER_API int XYParser_GetLeadMapCount(std::uint8_t channel_count);

// 获取指定导联数对应的导联映射表。
// @param channel_count 导联数。
// @param out_leads 输出的导联映射数组。
// @param max_leads 输出数组可写入的最大导联数，用于避免越界写入。
// @return 实际写入的导联数；如果参数无效则返回 0。
XYPARSER_API int XYParser_GetLeadMap(std::uint8_t channel_count,
                                     XYParserLeadChannelNumber* out_leads,
                                     int max_leads);

// 获取导联编号对应的名称字符串。
// @param lead 导联编号。
// @return 导联名称字符串；如果导联编号无效则返回 nullptr。
XYPARSER_API const char* XYParser_GetLeadName(XYParserLeadChannelNumber lead);

// 获取 Welch 频段索引对应的名称字符串。
// @param band_index Welch 频段索引。
// @return 频段名称字符串；如果索引无效则返回 nullptr。
XYPARSER_API const char* XYParser_GetWelchBandName(int band_index);

// 获取 Welch 频段索引对应的频率范围。
// @param band_index Welch 频段索引。
// @param out_low_hz 输出的频段下限频率，单位为 Hz。
// @param out_high_hz 输出的频段上限频率，单位为 Hz。
// @return 获取成功时返回非 0，失败时返回 0。
XYPARSER_API int XYParser_GetWelchBandRange(int band_index,
                                            double* out_low_hz,
                                            double* out_high_hz);

// 获取解析器最近一次错误的描述信息。
// @param handle 目标解析器句柄。
// @return 错误描述字符串；如果当前没有错误信息则返回 nullptr。
XYPARSER_API const char* XYParser_GetLastError(XYParserHandle handle);

}
