from pydantic import BaseModel, Field, validator
from typing import List, Any
import numpy

from src.utils import get_module_logger

logger = get_module_logger(__name__)

binary_data_types = (bytes, numpy.ndarray)


class AudioBinary_Config(BaseModel):
    """二进制音频块配置信息"""

    class Config:
        arbitrary_types_allowed = True

    audio_data: binary_data_types = Field(description="音频数据", default=None)
    chunk_size: int = Field(description="块大小", default=100)
    chunk_stride: int = Field(description="块步长", default=1600)
    sample_rate: int = Field(description="采样率", default=16000)
    sample_width: int = Field(description="采样位宽", default=2)
    channels: int = Field(description="通道数", default=1)

    # 从Dict中加载
    @classmethod
    def AudioBinary_Config_from_dict(cls, data: dict):
        return cls(**data)

    def ms2frame(self, ms: int) -> int:
        """
        将毫秒转换为帧
        """
        return int(ms * self.sample_rate / 1000)

    def frame2ms(self, frame: int) -> int:
        """
        将帧转换为毫秒
        """
        return int(frame * 1000 / self.sample_rate)


class _AudioBinary_data(BaseModel):
    """音频数据"""

    binary_data: binary_data_types = Field(description="音频二进制数据", default=None)

    class Config:
        arbitrary_types_allowed = True

    @validator("binary_data")
    def validate_binary_data(cls, v):
        """
        验证音频数据
        Args:
            v: 音频数据
        Returns:
            binary_data_types: 音频数据
        """
        if not isinstance(v, (bytes, numpy.ndarray)):
            logger.warning(
                "[%s]binary_data不是bytes, numpy.ndarray类型, 而是%s类型, 请检查",
                cls.__class__.__name__,
                type(v),
            )
        return v

    def __len__(self):
        """
        获取音频数据长度
        Returns:
            int: 音频数据长度
        """
        return len(self.binary_data)

    def __init__(self, binary_data: binary_data_types):
        """
        初始化音频数据
        Args:
            binary_data: 音频数据
        """
        logger.debug(
            "[%s]初始化音频数据, 数据类型为%s",
            self.__class__.__name__,
            type(binary_data),
        )
        super().__init__(binary_data=binary_data)

    def __getitem__(self):
        """
        当获取数据时, 直接返回binary_data
        Returns:
            binary_data_types: 音频数据
        """
        return self.binary_data


class AudioBinary_data_list(BaseModel):
    """音频数据列表"""

    binary_data_list: List[_AudioBinary_data] = Field(
        description="音频数据列表", default=[]
    )

    class Config:
        arbitrary_types_allowed = True

    def push_data(self, data: binary_data_types) -> int:
        """
        添加音频数据
        Args:
            data: 音频数据
        Returns:
            int: 数据在binary_data_list中的索引
        """
        self.binary_data_list.append(_AudioBinary_data(binary_data=data))
        return len(self.binary_data_list) - 1

    def __getitem__(self, index: int):
        """
        获取音频数据
        Args:
            index: 音频数据在binary_data_list中的索引
        Returns:
            _AudioBinary_data: 音频数据
        """
        return self.binary_data_list[index]

    def __len__(self):
        """
        获取音频数据列表长度
        Returns:
            int: 音频数据列表长度
        """
        return len(self.binary_data_list)


# class AudioBinary_Slice(BaseModel):
#     """音频块切片"""
#     target_Binary: AudioBinary_data_list = Field(description="目标音频块", default=None)
#     start_index: int = Field(description="开始位置", default=0)
#     end_index: int = Field(description="结束位置", default=-1)

#     @validator('start_index')
#     def validate_start_index(cls, v):
#         if v < 0:
#             raise ValueError("start_index必须大于0")
#         return v

#     @validator('end_index')
#     def validate_end_index(cls, v):
#         if v < cls.start_index:
#             logger.debug("[%s]end_index小于start_index, 将end_index设置为start_index", cls.__class__.__name__)
#             v = cls.start_index
#         return v

#     def __call__(self):
#         return self.target_Binary(self.start_index, self.end_index)
