#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
音频数据块管理类 - 用于存储和处理16KHz音频数据
"""

import numpy as np
import logging
from typing import List, Optional, Union
from src.models import AudioBinary_Config

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('AudioChunk')

class AudioChunk:
    """音频数据块管理类，用于存储和处理16KHz音频数据"""
    
    def __init__(self, 
                max_duration_ms: int = 1000*60*60*10,
                audio_config : AudioBinary_Config = None,
                ):
        """
        初始化音频数据块管理器
        
        参数:
            max_duration_ms: 音频池最大留存时间(ms)，默认10小时
            audio_config: 音频配置信息
        """
        # 音频参数
        self.sample_rate = audio_config.sample_rate if audio_config is not None else 16000   # 采样率：16KHz
        self.sample_width = audio_config.sample_width if audio_config is not None else 2     # 采样位宽：16bit
        self.channels = audio_config.channels if audio_config is not None else 1         # 通道数：单声道
        
        # 数据存储
        self._max_duration_ms = max_duration_ms
        self._max_chunk_size = self._time2size(max_duration_ms)  # 最大数据大小
        self._chunk = []  # 当前音频数据块列表
        self._chunk_size = 0    # 当前数据总大小
        self._offset = 0          # 当前偏移量
        
        logger.info(f"初始化AudioChunk: 最大时长={max_duration_ms}ms, 最大数据大小={self._max_chunk_size}字节")
    
    def add_chunk(self, chunk: Union[bytes, np.ndarray]) -> bool:
        """
        添加音频数据块
        
        参数:
            chunk: 音频数据块，可以是bytes或numpy数组
            
        返回:
            bool: 是否添加成功
        """
        try:
            # 检查数据格式
            if isinstance(chunk, np.ndarray):
                # 确保是16bit整数格式
                if chunk.dtype != np.int16:
                    chunk = chunk.astype(np.int16)
                # 转换为bytes
                chunk = chunk.tobytes()
            
            # 检查数据大小
            if len(chunk) % (self.sample_width * self.channels) != 0:
                logger.warning(f"音频数据大小不是{self.sample_width * self.channels}的倍数: {len(chunk)}")
                return False
            
            # 检查是否超过最大限制
            if self._chunk_size + len(chunk) > self._max_chunk_size:
                logger.warning("音频数据超过最大限制，将自动清除旧数据")
                self.clear_chunk()
            
            # 添加数据
            self._chunk.append(chunk)
            self._chunk_size += len(chunk)
            return True
            
        except Exception as e:
            logger.error(f"添加音频数据块时出错: {e}")
            return False
    
    def get_chunk_binary(self, start: int = 0, end: Optional[int] = None) -> Optional[bytes]:
        """
        获取指定索引的音频数据块
        """
        print("[AudioChunk] get_chunk_binary", start, end)
        if start >= len(self._chunk):
            return None
        if end is None or end > len(self._chunk):
            end = len(self._chunk)
        data = b''.join(self._chunk)
        return data[start:end]

    def get_chunk(self, start_ms: int = 0, end_ms: Optional[int] = None) -> Optional[bytes]:
        """
        获取指定时间范围的音频数据
        
        参数:
            start_ms: 开始时间(ms)
            end_ms: 结束时间(ms)，None表示到末尾
            
        返回:
            Optional[bytes]: 音频数据，如果获取失败则返回None
        """
        try:
            if not self._chunk:
                return None
            
            # 计算字节偏移
            start_byte = self._time2size(start_ms)
            end_byte = self._time2size(end_ms) if end_ms is not None else self._chunk_size

            # 检查范围是否有效
            if start_byte >= self._chunk_size or start_byte >= end_byte:
                return None
            
            # 获取数据
            data = b''.join(self._chunk)
            return data[start_byte:end_byte]
            
        except Exception as e:
            logger.error(f"获取音频数据块时出错: {e}")
            return None
    
    def get_duration(self) -> int:
        """
        获取当前音频总时长(ms)
        
        返回:
            int: 音频时长(ms)
        """
        return self._size2time(self._chunk_size)
    
    def clear_chunk(self) -> None:
        """清除所有音频数据"""
        self._chunk = []
        self._chunk_size = 0
        self._offset = 0
        logger.info("已清除所有音频数据")
    
    def _time2size(self, time_ms: int) -> int:
        """
        将时间(ms)转换为数据大小(字节)
        
        参数:
            time_ms: 时间(ms)
            
        返回:
            int: 数据大小(字节)
        """
        return int(time_ms * self.sample_rate * self.sample_width * self.channels / 1000)
    
    def _size2time(self, size: int) -> int:
        """
        将数据大小(字节)转换为时间(ms)
        
        参数:
            size: 数据大小(字节)
            
        返回:
            int: 时间(ms)
        """
        return int(size * 1000 / (self.sample_rate * self.sample_width * self.channels))
        
    # instance(start_ms, end_ms, use_offset=True)
    def __call__(self, start_ms: int = 0, end_ms: Optional[int] = None, use_offset: bool = True) -> Optional[bytes]:
        """
        获取指定时间范围的音频数据
        """
        if use_offset:
            start_ms += self._offset
            end_ms += self._offset
        return self.get_chunk(start_ms, end_ms)
        
    def __len__(self) -> int:
        """
        获取当前音频数据块大小
        """
        return self._chunk_size