# coding:utf-8

import os
import tempfile
import typing as t

from makit.web.headers import Headers
from makit.web.utils.concurrency import run_in_threadpool


class UploadFile:
    """
    An uploaded file included as part of the request data.
    """

    spool_max_size = 1024 * 1024
    file: t.BinaryIO
    headers: Headers

    def __init__(
            self,
            filename: str,
            file: t.Optional[t.BinaryIO] = None,
            content_type: str = "",
            *,
            headers: t.Optional[Headers] = None,
    ) -> None:
        self.filename = filename
        self.content_type = content_type
        if file is None:
            self.file = tempfile.SpooledTemporaryFile(max_size=self.spool_max_size)  # type: ignore  # noqa: E501
        else:
            self.file = file
        self.headers = headers or Headers()

    @property
    def _in_memory(self) -> bool:
        rolled_to_disk = getattr(self.file, "_rolled", True)
        return not rolled_to_disk

    async def write(self, data: bytes) -> None:
        if self._in_memory:
            self.file.write(data)
        else:
            await run_in_threadpool(self.file.write, data)

    async def read(self, size: int = -1) -> bytes:
        if self._in_memory:
            return self.file.read(size)
        return await run_in_threadpool(self.file.read, size)

    async def seek(self, offset: int) -> None:
        if self._in_memory:
            self.file.seek(offset)
        else:
            await run_in_threadpool(self.file.seek, offset)

    async def close(self) -> None:
        if self._in_memory:
            self.file.close()
        else:
            await run_in_threadpool(self.file.close)

    async def save(self, filename=None):
        if not filename:
            filename = self.filename
        os.makedirs(os.path.dirname(filename), exist_ok=True)
        with open(filename, 'wb') as f:
            f.write(await self.read())


class File:
    pass
