/**
 * 自然写教室智能网关管理软件 V1.0
 * 
 * ring_buffer.c - 线程安全环形缓冲区实现
 * 
 * 功能说明：
 * - 固定大小的无锁环形缓冲区（单生产者单消费者场景）
 * - 支持变长消息的读写（消息头+负载格式）
 * - 水位线监控与溢出保护
 * - 批量读取支持（减少锁竞争）
 * - 统计信息：写入/读取/丢弃计数
 * 
 * 用途：BLE接收线程 → 环形缓冲区 → MQTT发送线程
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>

/* ======================== 常量定义 ======================== */

/* 默认缓冲区大小 2MB (可存储约60,000条笔迹坐标) */
#define DEFAULT_BUFFER_SIZE     (2 * 1024 * 1024)

/* 单条消息最大长度 */
#define MAX_MESSAGE_SIZE        4096

/* 水位线阈值（百分比） */
#define HIGH_WATERMARK_PCT      80    /* 高水位告警阈值 */
#define LOW_WATERMARK_PCT       20    /* 低水位恢复阈值 */

/* 消息头魔数，用于数据完整性校验 */
#define MSG_HEADER_MAGIC        0xBEEF

/* ======================== 数据结构 ======================== */

/**
 * 消息头结构（每条消息在缓冲区中的前缀）
 * 用于在环形缓冲区中标识消息边界
 */
typedef struct {
    uint16_t magic;           /* 魔数校验 0xBEEF */
    uint16_t msg_type;        /* 消息类型（笔迹/事件/状态） */
    uint32_t payload_len;     /* 负载数据长度 */
    uint32_t timestamp;       /* 写入时间戳（秒） */
} __attribute__((packed)) ring_msg_header_t;

/**
 * 环形缓冲区统计信息
 */
typedef struct {
    uint64_t total_write;      /* 累计写入消息数 */
    uint64_t total_read;       /* 累计读取消息数 */
    uint64_t total_dropped;    /* 因缓冲区满而丢弃的消息数 */
    uint64_t total_bytes_in;   /* 累计写入字节数 */
    uint64_t total_bytes_out;  /* 累计读取字节数 */
    uint32_t peak_usage;       /* 历史最大使用量（字节） */
    uint32_t overflow_count;   /* 溢出次数 */
} ring_buffer_stats_t;

/**
 * 环形缓冲区主结构
 * 采用读写指针追赶模型：write_pos追赶read_pos表示满
 */
typedef struct {
    uint8_t           *buffer;          /* 缓冲区内存 */
    uint32_t           capacity;        /* 缓冲区总容量 */
    volatile uint32_t  write_pos;       /* 写入位置（生产者更新） */
    volatile uint32_t  read_pos;        /* 读取位置（消费者更新） */
    pthread_mutex_t    mutex;           /* 互斥锁（多生产者场景） */
    pthread_cond_t     not_empty;       /* 非空条件变量 */
    pthread_cond_t     not_full;        /* 非满条件变量 */
    ring_buffer_stats_t stats;          /* 统计信息 */
    bool               high_watermark;  /* 高水位标志 */
    bool               initialized;     /* 初始化标志 */
} ring_buffer_t;

/* ======================== 内部工具函数 ======================== */

/**
 * 计算缓冲区当前已使用字节数
 */
static uint32_t ring_buffer_used(const ring_buffer_t *rb)
{
    uint32_t wp = rb->write_pos;
    uint32_t rp = rb->read_pos;
    
    if (wp >= rp) {
        return wp - rp;
    } else {
        /* 写指针已回绕 */
        return rb->capacity - rp + wp;
    }
}

/**
 * 计算缓冲区剩余可用字节数
 * 预留1字节防止读写指针重合导致空/满状态混淆
 */
static uint32_t ring_buffer_free(const ring_buffer_t *rb)
{
    return rb->capacity - ring_buffer_used(rb) - 1;
}

/**
 * 将数据写入环形缓冲区（处理回绕）
 * 内部函数，调用者需确保空间足够
 */
static void ring_write_bytes(ring_buffer_t *rb, const uint8_t *data, 
                              uint32_t len)
{
    uint32_t wp = rb->write_pos;
    
    /* 计算到缓冲区末尾的连续空间 */
    uint32_t tail_space = rb->capacity - wp;
    
    if (len <= tail_space) {
        /* 无需回绕，直接拷贝 */
        memcpy(rb->buffer + wp, data, len);
    } else {
        /* 需要回绕：先写尾部，再写头部 */
        memcpy(rb->buffer + wp, data, tail_space);
        memcpy(rb->buffer, data + tail_space, len - tail_space);
    }
    
    /* 更新写指针（使用取模运算处理回绕） */
    rb->write_pos = (wp + len) % rb->capacity;
}

/**
 * 从环形缓冲区读取数据（处理回绕）
 * 内部函数，调用者需确保数据充足
 */
static void ring_read_bytes(ring_buffer_t *rb, uint8_t *data, uint32_t len)
{
    uint32_t rp = rb->read_pos;
    
    /* 计算到缓冲区末尾的连续数据 */
    uint32_t tail_data = rb->capacity - rp;
    
    if (len <= tail_data) {
        memcpy(data, rb->buffer + rp, len);
    } else {
        /* 回绕读取 */
        memcpy(data, rb->buffer + rp, tail_data);
        memcpy(data + tail_data, rb->buffer, len - tail_data);
    }
    
    /* 更新读指针 */
    rb->read_pos = (rp + len) % rb->capacity;
}

/**
 * 窥探缓冲区数据但不移动读指针
 * 用于预读消息头判断消息长度
 */
static void ring_peek_bytes(const ring_buffer_t *rb, uint8_t *data, 
                              uint32_t len)
{
    uint32_t rp = rb->read_pos;
    uint32_t tail_data = rb->capacity - rp;
    
    if (len <= tail_data) {
        memcpy(data, rb->buffer + rp, len);
    } else {
        memcpy(data, rb->buffer + rp, tail_data);
        memcpy(data + tail_data, rb->buffer, len - tail_data);
    }
}

/**
 * 检查并更新水位线状态
 * 高水位时触发告警，低水位时恢复
 */
static void check_watermark(ring_buffer_t *rb)
{
    uint32_t used = ring_buffer_used(rb);
    uint32_t usage_pct = (used * 100) / rb->capacity;
    
    /* 更新峰值记录 */
    if (used > rb->stats.peak_usage) {
        rb->stats.peak_usage = used;
    }
    
    if (!rb->high_watermark && usage_pct >= HIGH_WATERMARK_PCT) {
        rb->high_watermark = true;
        printf("[环形缓冲] 高水位告警: 使用率=%u%%, 已用=%u/%u字节\n",
               usage_pct, used, rb->capacity);
    } else if (rb->high_watermark && usage_pct <= LOW_WATERMARK_PCT) {
        rb->high_watermark = false;
        printf("[环形缓冲] 水位恢复正常: 使用率=%u%%\n", usage_pct);
    }
}

/* ======================== 公共接口 ======================== */

/**
 * 创建并初始化环形缓冲区
 * 
 * @param capacity  缓冲区容量（字节），0表示使用默认值2MB
 * @return 缓冲区指针，NULL表示失败
 */
ring_buffer_t *ring_buffer_create(uint32_t capacity)
{
    ring_buffer_t *rb = (ring_buffer_t *)calloc(1, sizeof(ring_buffer_t));
    if (rb == NULL) {
        printf("[环形缓冲] 内存分配失败\n");
        return NULL;
    }
    
    rb->capacity = (capacity > 0) ? capacity : DEFAULT_BUFFER_SIZE;
    rb->buffer = (uint8_t *)malloc(rb->capacity);
    if (rb->buffer == NULL) {
        printf("[环形缓冲] 缓冲区内存分配失败, 请求=%u字节\n", rb->capacity);
        free(rb);
        return NULL;
    }
    
    /* 初始化同步原语 */
    pthread_mutex_init(&rb->mutex, NULL);
    pthread_cond_init(&rb->not_empty, NULL);
    pthread_cond_init(&rb->not_full, NULL);
    
    rb->write_pos = 0;
    rb->read_pos = 0;
    rb->high_watermark = false;
    rb->initialized = true;
    
    memset(&rb->stats, 0, sizeof(rb->stats));
    
    printf("[环形缓冲] 初始化完成, 容量=%u字节 (%.1f MB)\n",
           rb->capacity, (float)rb->capacity / (1024 * 1024));
    
    return rb;
}

/**
 * 销毁环形缓冲区，释放所有资源
 */
void ring_buffer_destroy(ring_buffer_t *rb)
{
    if (rb == NULL) return;
    
    pthread_mutex_destroy(&rb->mutex);
    pthread_cond_destroy(&rb->not_empty);
    pthread_cond_destroy(&rb->not_full);
    
    if (rb->buffer) {
        free(rb->buffer);
    }
    
    printf("[环形缓冲] 已销毁, 总写入=%lu, 总读取=%lu, 丢弃=%lu\n",
           rb->stats.total_write, rb->stats.total_read, 
           rb->stats.total_dropped);
    
    free(rb);
}

/**
 * 写入一条消息到环形缓冲区
 * 消息格式：[ring_msg_header_t][payload_data]
 * 
 * @param rb          缓冲区指针
 * @param msg_type    消息类型
 * @param payload     消息负载数据
 * @param payload_len 负载长度
 * @return 0=成功, -1=消息过大, -2=缓冲区满
 */
int ring_buffer_write(ring_buffer_t *rb, uint16_t msg_type,
                       const uint8_t *payload, uint32_t payload_len)
{
    if (rb == NULL || !rb->initialized) return -1;
    
    /* 检查消息大小限制 */
    uint32_t total_size = sizeof(ring_msg_header_t) + payload_len;
    if (payload_len > MAX_MESSAGE_SIZE || total_size > rb->capacity / 2) {
        return -1;
    }
    
    pthread_mutex_lock(&rb->mutex);
    
    /* 检查剩余空间 */
    if (ring_buffer_free(rb) < total_size) {
        /* 缓冲区空间不足，丢弃消息 */
        rb->stats.total_dropped++;
        rb->stats.overflow_count++;
        pthread_mutex_unlock(&rb->mutex);
        return -2;
    }
    
    /* 构建消息头 */
    ring_msg_header_t header;
    header.magic = MSG_HEADER_MAGIC;
    header.msg_type = msg_type;
    header.payload_len = payload_len;
    header.timestamp = (uint32_t)time(NULL);
    
    /* 写入消息头 */
    ring_write_bytes(rb, (const uint8_t *)&header, sizeof(header));
    
    /* 写入消息负载 */
    if (payload_len > 0) {
        ring_write_bytes(rb, payload, payload_len);
    }
    
    /* 更新统计 */
    rb->stats.total_write++;
    rb->stats.total_bytes_in += total_size;
    
    /* 检查水位线 */
    check_watermark(rb);
    
    /* 通知等待的消费者 */
    pthread_cond_signal(&rb->not_empty);
    
    pthread_mutex_unlock(&rb->mutex);
    return 0;
}

/**
 * 从环形缓冲区读取一条消息
 * 
 * @param rb           缓冲区指针
 * @param msg_type     输出: 消息类型
 * @param payload      输出: 消息负载缓冲区
 * @param payload_max  负载缓冲区最大长度
 * @param payload_len  输出: 实际负载长度
 * @return 0=成功, -1=缓冲区空, -2=消息头损坏
 */
int ring_buffer_read(ring_buffer_t *rb, uint16_t *msg_type,
                      uint8_t *payload, uint32_t payload_max,
                      uint32_t *payload_len)
{
    if (rb == NULL || !rb->initialized) return -1;
    
    pthread_mutex_lock(&rb->mutex);
    
    /* 检查是否有数据可读 */
    uint32_t available = ring_buffer_used(rb);
    if (available < sizeof(ring_msg_header_t)) {
        pthread_mutex_unlock(&rb->mutex);
        return -1;
    }
    
    /* 预读消息头（不移动读指针） */
    ring_msg_header_t header;
    ring_peek_bytes(rb, (uint8_t *)&header, sizeof(header));
    
    /* 验证消息头魔数 */
    if (header.magic != MSG_HEADER_MAGIC) {
        /* 消息头损坏 - 尝试跳过一个字节寻找下一个有效消息头 */
        rb->read_pos = (rb->read_pos + 1) % rb->capacity;
        pthread_mutex_unlock(&rb->mutex);
        return -2;
    }
    
    /* 检查完整消息是否可用 */
    uint32_t total_size = sizeof(ring_msg_header_t) + header.payload_len;
    if (available < total_size) {
        /* 消息不完整，等待更多数据 */
        pthread_mutex_unlock(&rb->mutex);
        return -1;
    }
    
    /* 跳过消息头 */
    rb->read_pos = (rb->read_pos + sizeof(ring_msg_header_t)) % rb->capacity;
    
    /* 读取消息负载 */
    uint32_t read_len = header.payload_len;
    if (read_len > payload_max) {
        read_len = payload_max;
        /* 跳过剩余无法容纳的部分 */
        uint8_t discard_buf[256];
        uint32_t skip = header.payload_len - payload_max;
        while (skip > 0) {
            uint32_t chunk = (skip > sizeof(discard_buf)) ? 
                             sizeof(discard_buf) : skip;
            ring_read_bytes(rb, discard_buf, chunk);
            skip -= chunk;
        }
    }
    
    if (read_len > 0) {
        ring_read_bytes(rb, payload, read_len);
    }
    
    /* 输出结果 */
    if (msg_type)    *msg_type = header.msg_type;
    if (payload_len) *payload_len = read_len;
    
    /* 更新统计 */
    rb->stats.total_read++;
    rb->stats.total_bytes_out += total_size;
    
    /* 通知等待的生产者 */
    pthread_cond_signal(&rb->not_full);
    
    pthread_mutex_unlock(&rb->mutex);
    return 0;
}

/**
 * 获取缓冲区使用率百分比
 */
uint32_t ring_buffer_usage_percent(const ring_buffer_t *rb)
{
    if (rb == NULL || rb->capacity == 0) return 0;
    return (ring_buffer_used(rb) * 100) / rb->capacity;
}

/**
 * 获取缓冲区统计信息副本
 */
void ring_buffer_get_stats(const ring_buffer_t *rb, ring_buffer_stats_t *stats)
{
    if (rb == NULL || stats == NULL) return;
    memcpy(stats, &rb->stats, sizeof(ring_buffer_stats_t));
}

/**
 * 清空缓冲区所有数据
 */
void ring_buffer_flush(ring_buffer_t *rb)
{
    if (rb == NULL) return;
    
    pthread_mutex_lock(&rb->mutex);
    rb->write_pos = 0;
    rb->read_pos = 0;
    rb->high_watermark = false;
    printf("[环形缓冲] 已清空, 丢弃消息=%lu\n", rb->stats.total_dropped);
    pthread_mutex_unlock(&rb->mutex);
}
