/**
 * 自然写互动课堂应用开发SDK软件 V1.0
 * BLE协议解析核心模块 - 蓝牙5.0点阵笔通信协议实现
 *
 * 跨平台C语言核心库，负责解析点阵笔BLE GATT数据
 * 提供笔迹坐标解包、协议帧校验、数据压缩解压等底层能力
 * 通过JNI/ObjC Bridge/FFI供各平台SDK调用
 */

#ifndef BLE_PROTOCOL_H
#define BLE_PROTOCOL_H

#include <stdint.h>
#include <stddef.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== 协议常量定义 ==================== */

/* BLE GATT Service UUID（自定义服务） */
#define WRITECH_SERVICE_UUID        "0000FFE0-0000-1000-8000-00805F9B34FB"
/* 笔迹数据Characteristic UUID */
#define STROKE_DATA_CHAR_UUID       "0000FFE1-0000-1000-8000-00805F9B34FB"
/* 设备信息Characteristic UUID */
#define DEVICE_INFO_CHAR_UUID       "0000FFE2-0000-1000-8000-00805F9B34FB"
/* 配置写入Characteristic UUID */
#define CONFIG_WRITE_CHAR_UUID      "0000FFE3-0000-1000-8000-00805F9B34FB"
/* OTA DFU Characteristic UUID */
#define OTA_DFU_CHAR_UUID           "0000FFE4-0000-1000-8000-00805F9B34FB"

/* 协议帧标志 */
#define FRAME_HEADER_MAGIC          0xAA55
#define FRAME_MAX_PAYLOAD_SIZE      240     /* MTU=247, 减去帧头7字节 */
#define MAX_POINTS_PER_FRAME        34      /* 每帧最多34个坐标点 */

/* 帧类型定义 */
#define FRAME_TYPE_STROKE_DATA      0x01    /* 笔迹坐标数据 */
#define FRAME_TYPE_PEN_UP           0x02    /* 抬笔事件 */
#define FRAME_TYPE_PEN_DOWN         0x03    /* 落笔事件 */
#define FRAME_TYPE_DEVICE_STATUS    0x04    /* 设备状态（电量等） */
#define FRAME_TYPE_OFFLINE_SYNC     0x05    /* 离线数据同步 */
#define FRAME_TYPE_OTA_DATA         0x06    /* OTA升级数据 */
#define FRAME_TYPE_CONFIG_RSP       0x07    /* 配置响应 */

/* ==================== 数据结构定义 ==================== */

/**
 * 原始笔迹坐标点（7字节紧凑编码）
 * x: 16位无符号整数，点阵坐标X（分辨率约300DPI）
 * y: 16位无符号整数，点阵坐标Y
 * pressure: 8位无符号整数，压力值(0-255)
 * timestamp_delta: 16位无符号整数，距上一点的时间差(毫秒)
 */
typedef struct {
    uint16_t x;                 /* X坐标（大端序） */
    uint16_t y;                 /* Y坐标（大端序） */
    uint8_t  pressure;          /* 压力值 0-255 */
    uint16_t timestamp_delta;   /* 时间增量（毫秒） */
} __attribute__((packed)) StrokePointRaw;

/**
 * 解码后的笔迹坐标点
 */
typedef struct {
    float x;                    /* X坐标（浮点） */
    float y;                    /* Y坐标（浮点） */
    float pressure;             /* 压力值 0.0-1.0 */
    uint32_t timestamp;         /* 绝对时间戳（毫秒） */
    uint8_t pen_state;          /* 0=落笔, 1=抬笔 */
} StrokePoint;

/**
 * BLE协议帧头（7字节）
 */
typedef struct {
    uint16_t magic;             /* 帧头魔数 0xAA55 */
    uint8_t  frame_type;        /* 帧类型 */
    uint8_t  sequence;          /* 帧序号(0-255循环) */
    uint16_t payload_length;    /* 负载长度 */
    uint8_t  checksum;          /* 帧头校验和(XOR) */
} __attribute__((packed)) FrameHeader;

/**
 * 笔迹数据帧
 */
typedef struct {
    FrameHeader header;
    uint8_t point_count;        /* 本帧包含的坐标点数 */
    uint32_t page_id;           /* 点阵码页面ID */
    StrokePointRaw points[MAX_POINTS_PER_FRAME];  /* 坐标点数组 */
    uint16_t crc16;             /* CRC-16校验 */
} __attribute__((packed)) StrokeDataFrame;

/**
 * 设备状态帧
 */
typedef struct {
    FrameHeader header;
    uint8_t  battery_level;     /* 电量百分比 0-100 */
    uint8_t  charging_state;    /* 充电状态: 0=未充电, 1=充电中, 2=已充满 */
    uint16_t firmware_version;  /* 固件版本 (major*256+minor) */
    uint8_t  connection_state;  /* 连接状态 */
    uint32_t serial_number;     /* 设备序列号 */
    uint16_t crc16;
} __attribute__((packed)) DeviceStatusFrame;

/**
 * 解析回调函数类型定义
 */
typedef void (*on_stroke_point_cb)(const StrokePoint* point, void* user_data);
typedef void (*on_pen_event_cb)(uint8_t event_type, uint32_t timestamp, void* user_data);
typedef void (*on_device_status_cb)(uint8_t battery, uint8_t charging, uint16_t fw_ver, void* user_data);

/* ==================== 协议解析器 ==================== */

/**
 * BLE协议解析器上下文
 */
typedef struct {
    /* 接收缓冲区（处理分包/粘包） */
    uint8_t recv_buffer[512];
    size_t  recv_length;
    
    /* 序号跟踪（乱序检测） */
    uint8_t expected_sequence;
    
    /* 时间戳基准 */
    uint32_t base_timestamp;
    uint32_t last_timestamp;
    
    /* 统计信息 */
    uint32_t total_frames;
    uint32_t total_points;
    uint32_t error_frames;
    uint32_t lost_frames;
    
    /* 回调函数 */
    on_stroke_point_cb stroke_cb;
    on_pen_event_cb pen_event_cb;
    on_device_status_cb status_cb;
    void* user_data;
} BleProtocolParser;

/**
 * 初始化协议解析器
 */
static inline void ble_parser_init(BleProtocolParser* parser) {
    memset(parser, 0, sizeof(BleProtocolParser));
    parser->expected_sequence = 0;
    parser->base_timestamp = 0;
}

/**
 * 设置回调函数
 */
static inline void ble_parser_set_callbacks(
    BleProtocolParser* parser,
    on_stroke_point_cb stroke_cb,
    on_pen_event_cb pen_event_cb,
    on_device_status_cb status_cb,
    void* user_data
) {
    parser->stroke_cb = stroke_cb;
    parser->pen_event_cb = pen_event_cb;
    parser->status_cb = status_cb;
    parser->user_data = user_data;
}

/**
 * 计算CRC-16校验值（CCITT标准）
 */
static uint16_t calc_crc16(const uint8_t* data, size_t length) {
    uint16_t crc = 0xFFFF;
    for (size_t i = 0; i < length; i++) {
        crc ^= (uint16_t)data[i] << 8;
        for (int j = 0; j < 8; j++) {
            if (crc & 0x8000)
                crc = (crc << 1) ^ 0x1021;
            else
                crc <<= 1;
        }
    }
    return crc;
}

/**
 * 校验帧头
 */
static int validate_frame_header(const FrameHeader* header) {
    /* 校验魔数 */
    if (header->magic != FRAME_HEADER_MAGIC) return -1;
    /* 校验负载长度 */
    if (header->payload_length > FRAME_MAX_PAYLOAD_SIZE) return -2;
    /* 校验帧头XOR校验和 */
    uint8_t xor_sum = 0;
    const uint8_t* p = (const uint8_t*)header;
    for (int i = 0; i < 6; i++) xor_sum ^= p[i];
    if (xor_sum != header->checksum) return -3;
    return 0;
}

/**
 * 大端序转小端序（16位）
 */
static inline uint16_t be16_to_le(uint16_t value) {
    return (value >> 8) | (value << 8);
}

/**
 * 解析笔迹数据帧
 * 从帧中提取坐标点并通过回调函数输出
 */
static int parse_stroke_frame(BleProtocolParser* parser, const uint8_t* data, size_t length) {
    if (length < sizeof(FrameHeader) + 5) return -1;

    const FrameHeader* header = (const FrameHeader*)data;
    
    /* 帧头校验 */
    if (validate_frame_header(header) != 0) {
        parser->error_frames++;
        return -1;
    }

    /* 序号连续性检查 */
    if (header->sequence != parser->expected_sequence) {
        uint8_t lost = header->sequence - parser->expected_sequence;
        parser->lost_frames += lost;
    }
    parser->expected_sequence = header->sequence + 1;

    /* 解析负载 */
    const uint8_t* payload = data + sizeof(FrameHeader);
    uint8_t point_count = payload[0];
    uint32_t page_id = *(uint32_t*)(payload + 1);

    if (point_count > MAX_POINTS_PER_FRAME) {
        parser->error_frames++;
        return -2;
    }

    /* CRC校验（校验帧头+负载） */
    size_t crc_data_len = length - 2;
    uint16_t expected_crc = *(uint16_t*)(data + crc_data_len);
    uint16_t actual_crc = calc_crc16(data, crc_data_len);
    if (expected_crc != actual_crc) {
        parser->error_frames++;
        return -3;
    }

    /* 解析每个坐标点 */
    const StrokePointRaw* raw_points = (const StrokePointRaw*)(payload + 5);
    for (int i = 0; i < point_count; i++) {
        StrokePoint decoded;
        decoded.x = (float)be16_to_le(raw_points[i].x);
        decoded.y = (float)be16_to_le(raw_points[i].y);
        decoded.pressure = raw_points[i].pressure / 255.0f;
        
        /* 累加时间增量得到绝对时间戳 */
        uint16_t delta = be16_to_le(raw_points[i].timestamp_delta);
        parser->last_timestamp += delta;
        decoded.timestamp = parser->base_timestamp + parser->last_timestamp;
        decoded.pen_state = 0; /* 落笔状态 */

        /* 通过回调函数输出 */
        if (parser->stroke_cb) {
            parser->stroke_cb(&decoded, parser->user_data);
        }
        parser->total_points++;
    }

    parser->total_frames++;
    return point_count;
}

/**
 * 输入BLE Notify接收到的数据
 * 处理分包/粘包，自动检测帧边界并分发解析
 */
static int ble_parser_feed(BleProtocolParser* parser, const uint8_t* data, size_t length) {
    /* 追加到接收缓冲区 */
    if (parser->recv_length + length > sizeof(parser->recv_buffer)) {
        /* 缓冲区溢出，丢弃旧数据 */
        parser->recv_length = 0;
    }
    memcpy(parser->recv_buffer + parser->recv_length, data, length);
    parser->recv_length += length;

    int parsed_count = 0;

    /* 扫描缓冲区查找完整帧 */
    while (parser->recv_length >= sizeof(FrameHeader)) {
        /* 查找帧头魔数 */
        if (parser->recv_buffer[0] != 0xAA || parser->recv_buffer[1] != 0x55) {
            /* 跳过非法字节 */
            memmove(parser->recv_buffer, parser->recv_buffer + 1, parser->recv_length - 1);
            parser->recv_length--;
            continue;
        }

        FrameHeader* header = (FrameHeader*)parser->recv_buffer;
        size_t frame_size = sizeof(FrameHeader) + header->payload_length + 2; /* +2 for CRC */

        if (parser->recv_length < frame_size) {
            break; /* 帧数据不完整，等待更多数据 */
        }

        /* 根据帧类型分发解析 */
        switch (header->frame_type) {
            case FRAME_TYPE_STROKE_DATA:
                parse_stroke_frame(parser, parser->recv_buffer, frame_size);
                parsed_count++;
                break;
            case FRAME_TYPE_PEN_UP:
                if (parser->pen_event_cb) {
                    parser->pen_event_cb(1, parser->last_timestamp, parser->user_data);
                }
                break;
            case FRAME_TYPE_PEN_DOWN:
                if (parser->pen_event_cb) {
                    parser->pen_event_cb(0, parser->last_timestamp, parser->user_data);
                }
                break;
            case FRAME_TYPE_DEVICE_STATUS: {
                DeviceStatusFrame* status = (DeviceStatusFrame*)parser->recv_buffer;
                if (parser->status_cb) {
                    parser->status_cb(status->battery_level, status->charging_state,
                                      status->firmware_version, parser->user_data);
                }
                break;
            }
            default:
                break;
        }

        /* 移除已处理的帧 */
        memmove(parser->recv_buffer, parser->recv_buffer + frame_size,
                parser->recv_length - frame_size);
        parser->recv_length -= frame_size;
    }

    return parsed_count;
}

/**
 * 获取解析器统计信息
 */
static inline void ble_parser_get_stats(const BleProtocolParser* parser,
    uint32_t* total_frames, uint32_t* total_points,
    uint32_t* error_frames, uint32_t* lost_frames) {
    if (total_frames) *total_frames = parser->total_frames;
    if (total_points) *total_points = parser->total_points;
    if (error_frames) *error_frames = parser->error_frames;
    if (lost_frames)  *lost_frames  = parser->lost_frames;
}

/**
 * 重置解析器状态
 */
static inline void ble_parser_reset(BleProtocolParser* parser) {
    parser->recv_length = 0;
    parser->expected_sequence = 0;
    parser->last_timestamp = 0;
    parser->total_frames = 0;
    parser->total_points = 0;
    parser->error_frames = 0;
    parser->lost_frames = 0;
}

#ifdef __cplusplus
}
#endif

#endif /* BLE_PROTOCOL_H */
