import math, asyncio, subprocess
from telethon import TelegramClient
from aiohttp import web

import logging

logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


class Download:
    client: TelegramClient
    route: str
    offset: int
    handler: None
    file: None
    limit: int
    file_size: float

    def __init__(self, handler):
        self.handler = handler
        self.file = handler.message.media
        self.file_size = handler.message.file.size
        self.limit = handler.sanity.limit
        self.offset = handler.sanity.offset
        self.client = handler.client
        self.mime_type = handler.message.file.mime_type

    async def download(self):
        part_size = int(512 * 1024) * 2
        first_part_cut = self.offset % part_size
        first_part = math.floor(self.offset / part_size)
        last_part_cut = part_size - (self.limit % part_size)
        last_part = math.ceil(self.limit / part_size)
        part_count = math.ceil(self.file_size / part_size)
        part = first_part
        try:
            async for chunk in self.client.iter_download(
                self.file, offset=first_part * part_size, request_size=part_size
            ):

                if part == first_part:
                    yield chunk[first_part_cut:]
                elif part == last_part:
                    yield chunk[:last_part_cut]
                else:
                    yield chunk
                logging.debug(f"Part {part}/{last_part} (total {part_count}) served!")
                part += 1
            logging.debug("serving finished")
        except (GeneratorExit, StopAsyncIteration, asyncio.CancelledError):
            logging.debug("file serve interrupted")

            raise
        except Exception as e:
            print(e)
            logging.debug("file serve errored", exc_info=True)

    async def handle_request(self):
        headers = {
            "content-type": self.mime_type,
            "content-range": f"bytes {self.offset}-{self.limit-1}/{self.file_size}",
            "content-length": str(self.limit - self.offset),
            "accept-ranges": "bytes",
            "content-transfer-encoding": "Binary",
            "content-disposition": f'{self.handler.route}; filename="{self.handler.message.file.name}"',
        }
        logging.info(
            f"Serving file in {self.handler.message.file.name}) ; Range: {self.offset} - {self.limit}"
        )
        if self.handler.head:
            body = None
        else:

            body = self.download()
            # if body:

            #     ffmpeg = "ffmpeg"

            #     cmd = [
            #         ffmpeg,
            #         "ffmpeg",
            #         "-i",
         

            #         "pipe:0",
            #         "-c",
            #         "copy",
            #         "-re",
              
            #         "pipe:1",
            #     ]
            #     ffmpeg_cmd = subprocess.Popen(
            #         cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False
            #     )
            #     body = await body.__anext__()
            #     ffmpeg_cmd.stdin.write(body.tobytes())
            #     ffmpeg_cmd.stdin.close()
            #     body = b""
            #     while True:
            #         print(body)
            #         output = ffmpeg_cmd.stdout.read()

            #         if len(output) > 0:
            #             body += output
            #             ffmpeg_cmd.stdout.close()

            #         else:
            #             error_msg = ffmpeg_cmd.poll()
            #             if error_msg is not None:
            #                 break

        return web.Response(
            body=body, headers=headers, status=206 if self.offset else 200
        )