# -*- coding: utf-8 -*-
"""
FileSlice 文件分片

从文件读取数据，支持指定范围。
"""

import os
import aiofiles
from typing import Optional

from .base import SimpleSlice


class FileSlice(SimpleSlice):
    """
    文件分片读取器
    
    从文件读取数据。
    
    属性:
        _f: 文件对象（aiofiles）
    """

    def __init__(self, data: str) -> None:
        """
        初始化文件分片
        
        Args:
            data: 文件路径
        
        Raises:
            FileNotFoundError: 文件不存在
            TypeError: 数据类型不支持
        """
        super().__init__()

        if not isinstance(data, str):
            raise TypeError(f"不支持的类型: {type(data)}，期望 str")

        if not os.path.exists(data):
            raise FileNotFoundError(f"文件不存在: {data}")

        self._data_path = data
        self._f: Optional[aiofiles.threadpool.binary.AsyncBufferedIOBase] = None
        self._position = 0
        
        # 初始化时获取文件长度
        with open(self._data_path, "rb") as f:
            f.seek(0, 2)
            self._length = f.tell()

    async def _open_file(self) -> None:
        """
        打开文件并计算长度
        """
        if self._f is not None:
            return

        self._f = await aiofiles.open(self._data_path, "rb")
        await self._f.seek(0, 2)
        total = await self._f.tell()
        await self._f.seek(0, 0)

        self._length = total

    async def read_abstract(self, size: int) -> bytes:
        """
        读取原始数据
        
        Args:
            size: 读取的字节数
        
        Returns:
            bytes: 原始数据
        
        Raises:
            ValueError: 读取失败
        """
        await self._open_file()

        if self._f is None:
            raise ValueError("文件对象未初始化")

        try:
            await self._f.seek(self._position)
            data = await self._f.read(size)
            return data
        except Exception as e:
            raise ValueError(f"读取失败: {e}") from e
    
    async def _close(self) -> None:
        """
        关闭文件资源
        """
        if self._f is None:
            return

        try:
            await self._f.close()
        except Exception:
            pass

        self._f = None
