# -*- coding: utf-8 -*-

import logging
from ...functions.Human_Format import human_readable_bytes, human_readable_timedelta
from ..getVars import get_val
from telethon.errors.rpcerrorlist import MessageNotModifiedError, FloodWaitError
from telethon.tl.types import KeyboardButtonCallback
from datetime import datetime

torlog = logging.getLogger(__name__)

class Status():
    # Shared List
    Tasks = []
    
    def __init__(self):
        self._task_id = len(self.Tasks) + 1

    def refresh_info(self):
        raise NotImplementedError

    def update_message(self):
        raise NotImplementedError

    def is_active(self):
        raise NotImplementedError

    def set_inactive(self):
        raise NotImplementedError

# qBittorrent Task Class
class QBTask(Status):
    
    def __init__(self, torrent, message, client):
        super().__init__()
        self.Tasks.append(self)
        self.hash = torrent.hash
        self._torrent = torrent
        self._message = message
        self._client = client
        self._active = True
        self._path = torrent.save_path
        self._error = ""
        self._done = False
        self.cancel = False
        self._omess = None
        self._prevmsg = ""
    
    async def set_original_mess(self, omess):
        self._omess = omess
    
    async def get_original_message(self):
        return self._omess

    async def refresh_info(self, torrent = None):
        if torrent is None:
            self._torrent = self._client.torrents_info(torrent_hashes=self._torrent.hash)
        else:
            self._torrent = torrent

    async def get_sender_id(self):
        return self._omess.sender_id

    async def create_message(self):
        msg = "<b>downloading:</b> <code>{}</code>\n".format(
            self._torrent.name
            )
        msg += "<b>down:</b> {} <b>up:</b> {}\n".format(
            human_readable_bytes(self._torrent.dlspeed,postfix="/s"),
            human_readable_bytes(self._torrent.upspeed,postfix="/s")
            )
        msg += "<b>progress:</b> {} - {}%\n".format(
            self.progress_bar(self._torrent.progress),
            round(self._torrent.progress*100,2)
            )
        msg += "<b>downloaded:</b> {} out of {}\n".format(
            human_readable_bytes(self._torrent.downloaded),
            human_readable_bytes(self._torrent.total_size)
            )
        msg += "<b>eta:</b> <b>{}</b>\n".format(
            human_readable_timedelta(self._torrent.eta)
            )
        msg += "<b>s:</b>{} <b>l:</b>{}\n".format(
            self._torrent.num_seeds,self._torrent.num_leechs
            )
        msg += "<b>using engine:</b> <code>qBittorrent</code>"

        return msg

    async def get_state(self):
        #stalled
        if self._torrent.state == "stalledDL":
            return"torrent <code>{}</code> stalled (waiting for connection) temporarily.".format(self._torrent.name)
        #meta stage
        elif self._torrent.state == "metaDL":
            return  "getting metadata for {} - {}".format(self._torrent.name,datetime.now().strftime("%H:%M:%S"))
        elif self._torrent.state == "downloading" or self._torrent.state.lower().endswith("dl"):
            # kept for past ref
            return None

    async def central_message(self):
        cstate = await self.get_state()
        if cstate is not None:
            return cstate
        else:
            return await self.create_message()

    async def update_message(self):
        msg = await self.create_message()
        if self._prevmsg == msg:
            return

        self._prevmsg = msg
        
        try:
        
            cstate = await self.get_state()
            
            msg = cstate if cstate is not None else msg
            
            await self._message.edit(msg,parse_mode="html",buttons=self._message.reply_markup) 

        except MessageNotModifiedError as e:
            torlog.debug("{}".format(e))
        except FloodWaitError as e:
            torlog.error("{}".format(e))
        except Exception as e:
            torlog.info("not expected {}".format(e))


    async def set_done(self):
        self._done = True
        await self.set_inactive()

    def is_done(self):
        return self._done

    async def set_path(self, path):
        self._path = path

    async def get_path(self):
        return self._path

    async def set_inactive(self, error=None):
        self._active = False
        if error is not None:
            self._error = error

    async def is_active(self):
        return self._active

    def progress_bar(self, percentage):
        """Returns a progress bar for download
        """
        #percentage is on the scale of 0-1
        comp = get_val("COMPLETED_STR")
        ncomp = get_val("REMAINING_STR")
        pr = ""

        for i in range(1,11):
            if i <= int(percentage*10):
                pr += comp
            else:
                pr += ncomp
        return pr


class ARTask(Status):
    
    def __init__(self, gid, message, aria2, dl_file):
        super().__init__()
        self.Tasks.append(self)
        self._gid = gid
        self._dl_file = dl_file 
        self._message = message
        self._aria2 = aria2
        self._active = True
        self._error = ""
        self._done = False
        self.cancel = False
        self._omess = None
        self._path =None 
        self._prevmsg = ""
    # Setters

    async def set_original_mess(self, omess=None):
        if omess is None:
            omess = await self._message.get_reply_message()

        self._omess = omess

    async def get_original_message(self):
        return self._omess

    async def get_gid(self):
        return self._gid

    async def set_gid(self, gid):
        self._gid = gid
    
    async def get_sender_id(self):
        return self._omess.sender_id

    async def refresh_info(self, dl_file = None):
        if dl_file is None:
            try:
                self._dl_file = self._aria2.get_download(self._gid)
            except:
                torlog.exception("error fetching direct download link.")
        else:
            self._dl_file = dl_file

    async def create_message(self):
        # Getting the vars pre handed
        downloading_dir_name = "N/A"
        try:
            downloading_dir_name = str(self._dl_file.name)
        except:
            pass

        msg = "<b>downloading:</b> <code>{}</code>\n".format(
            downloading_dir_name
            )
        msg += "<b>down:</b> {} <b>Up:</b> {}\n".format(
            self._dl_file.download_speed_string(),
            self._dl_file.upload_speed_string()
            )
        msg += "<b>progress:</b> {} - {}%\n".format(
            self.progress_bar(self._dl_file.progress/100),
            round(self._dl_file.progress,2)
            )
        msg += "<b>downloaded:</b> {} out of {}\n".format(
            human_readable_bytes(self._dl_file.completed_length),
            human_readable_bytes(self._dl_file.total_length)
            )
        msg += "<b>eta:</b> <b>{}</b>\n".format(
            self._dl_file.eta_string()
            )
        msg += "<b>conns:  </b>{} <b>\n".format(
            self._dl_file.connections
            )
        msg += "<b>using engine:</b> <code>aria2</code>"

        return msg

    async def get_state(self):
        # No states for aria2
        pass

    async def central_message(self):
        return await self.create_message()

    async def update_message(self):
        msg = await self.create_message()
        if self._prevmsg == msg:
            return
        
        self._prevmsg = msg
        
        try:
            data = "torcancel aria2 {} {}".format(
                self._gid,
                self._omess.sender_id
            )
            await self._message.edit(msg,parse_mode="html",buttons=[KeyboardButtonCallback("cancel direct leech",data=data.encode("UTF-8"))]) 

        except MessageNotModifiedError as e:
            torlog.debug("{}".format(e))
        except FloodWaitError as e:
            torlog.error("{}".format(e))
        except Exception as e:
            torlog.info("Not expected {}".format(e))

    async def set_done(self):
        self._done = True
        await self.set_inactive()

    def is_done(self):
        return self._done

    async def set_inactive(self, error=None):
        self._active = False
        if error is not None:
            self._error = error

    async def is_active(self):
        return self._active

    async def get_error(self):
        return self._error

    async def set_path(self, path):
        self._path = path

    async def get_path(self):
        return self._path

    def progress_bar(self, percentage):
        """Returns a progress bar for download
        """
        #percentage is on the scale of 0-1
        comp = get_val("COMPLETED_STR")
        ncomp = get_val("REMAINING_STR")
        pr = ""

        for i in range(1,11):
            if i <= int(percentage*10):
                pr += comp
            else:
                pr += ncomp
        return pr