# -*- coding: utf-8 -*-
"""
MixSlice 组合分片

将多个 SimpleSlice 组合成一个整体。
"""

from typing import List

from .base import SimpleSlice


class MixSlice(SimpleSlice):
    """
    组合分片读取器
    
    将多个 SimpleSlice 实例组合成一个连续的整体。
    
    属性:
        _slices: 子分片列表
        _slice_offsets: 每个子分片的起始位置
    """

    def __init__(self, slices: List[SimpleSlice]) -> None:
        """
        初始化组合分片
        
        Args:
            slices: 子分片列表
        
        Raises:
            ValueError: 参数错误
        """
        super().__init__()

        if not slices:
            raise ValueError("子分片列表不能为空")

        self._slices = slices
        self._slice_offsets = [0]

        total_length = 0
        for slice_obj in slices:
            total_length += len(slice_obj)
            self._slice_offsets.append(total_length)

        self._length = total_length
        self._position = 0

    async def read_abstract(self, size: int) -> bytes:
        """
        读取原始数据
        
        自动跨子分片读取数据。
        
        Args:
            size: 读取的字节数
        
        Returns:
            bytes: 原始数据
        """
        result = bytearray()
        remaining = size

        while remaining > 0 and self._position < self._length:
            slice_index = self._find_slice_index(self._position)

            if slice_index >= len(self._slices):
                break

            slice_obj = self._slices[slice_index]
            slice_offset = self._slice_offsets[slice_index]
            slice_position = self._position - slice_offset

            await slice_obj.seek(slice_position)
            read_size = min(remaining, len(slice_obj) - slice_position)

            data = await slice_obj.read(read_size)
            result.extend(data)

            self._position += len(data)
            remaining -= len(data)

        return bytes(result)

    def _find_slice_index(self, position: int) -> int:
        """
        查找包含指定位置的子分片索引
        
        Args:
            position: 位置（相对于整体）
        
        Returns:
            int: 子分片索引
        """
        for i, offset in enumerate(self._slice_offsets):
            if position < offset:
                return i - 1

        return len(self._slices) - 1

    async def _close(self) -> None:
        """
        关闭所有子分片的资源
        """
        for slice_obj in self._slices:
            try:
                await slice_obj.close()
            except Exception:
                pass

        self._slices = []
        self._slice_offsets = []
