# -*- coding: utf-8 -*-
# vStream https://github.com/Kodi-vStream/venom-xbmc-addons

try:
    import urllib2

except ImportError:
    import urllib.request as urllib2

import re
import threading
import xbmcplugin
import xbmcvfs
import xbmcgui
import xbmc

from resources.lib.comaddon import addon, dialog, progress, VSlog, VSupdate, VSPath
from resources.lib.db import cDb
from resources.lib.gui.gui import cGui
from resources.lib.gui.guiElement import cGuiElement
from resources.lib.handler.inputParameterHandler import cInputParameterHandler
from resources.lib.handler.outputParameterHandler import cOutputParameterHandler
from resources.lib.handler.pluginHandler import cPluginHandler
from resources.lib.player import cPlayer
from resources.lib.util import cUtil, UnquotePlus

# try:
#     import StorageServer
#     Memorise = StorageServer.StorageServer('VstreamDownloader')
# except:
#     print('Le download ne marchera pas correctement')


SITE_IDENTIFIER = 'cDownload'

# http://kodi.wiki/view/Add-on:Common_plugin_cache
# https://pymotw.com/2/threading/
# https://code.google.com/p/navi-x/source/browse/trunk/Navi-X/src/CDownLoader.py?r=155

# status = 0 => pas telechargé
# status = 1 => en cours de DL (ou bloque si bug)
# status = 2 => fini de DL

# GetProperty('arret') = '0' => Telechargement en cours
# GetProperty('arret') = '1' => Arret demandé
# GetProperty('arret') = '' =>  Jamais eu de telechargement


class cDownloadProgressBar(threading.Thread):
    DIALOG = dialog()
    ADDON = addon()

    def __init__(self, *args, **kwargs):

        self.__sTitle = ''
        self.__sUrl = ''
        self.__fPath = ''
        self.__bFastMode = False

        if kwargs:
            self.__sTitle = kwargs['title']
            self.__sUrl = kwargs['url']
            self.__fPath = kwargs['Dpath']
            if 'FastMode' in kwargs:
                print('Téléchargement en mode Turbo')
                self.__bFastMode = True

        threading.Thread.__init__(self)

        self.processIsCanceled = False
        self.oUrlHandler = None
        self.file = None
        self.__oDialog = None

        # self.currentThread = threading.Thread(target=self.run)
        # self.currentThread.start()

    def createProcessDialog(self):
        self.__oDialog = xbmcgui.DialogProgressBG()
        self.__oDialog.create('Download')
        # xbmc.sleep(1000)
        return self.__oDialog

    def _StartDownload(self):

        # print('Thread actuel')
        # print(threading.current_thread().getName())

        diag = self.createProcessDialog()
        # diag.isFinished()

        xbmcgui.Window(10101).setProperty('arret', '0')
        # self.Memorise.set('VstreamDownloaderWorking', '1')

        headers = self.oUrlHandler.info()

        # print(headers)

        iTotalSize = -1
        if 'content-length' in headers:
            iTotalSize = int(headers['Content-Length'])

        chunk = 16 * 1024
        TotDown = 0

        # mise a jour pour info taille
        self.__updatedb(TotDown, iTotalSize)
        self.DIALOG.VSinfo(self.ADDON.VSlang(30086))

        while not (self.processIsCanceled or diag.isFinished()):

            data = self.oUrlHandler.read(chunk)
            if not data:
                print('DL err')
                break

            self.file.write(data)
            TotDown = TotDown + data.__len__()
            self.__updatedb(TotDown, iTotalSize)

            self.__stateCallBackFunction(TotDown, iTotalSize)
            # if self.Memorise.get('VstreamDownloaderWorking') == '0':
                # self.processIsCanceled = True
            if xbmcgui.Window(10101).getProperty('arret') == '1':
                self.processIsCanceled = True

            # petite pause, ca ralentit le download mais evite de bouffer 100/100 ressources
            if not self.__bFastMode:
                xbmc.sleep(300)

        self.oUrlHandler.close()
        self.file.close()
        self.__oDialog.close()

        # On autorise le prochain DL
        # ????????????????
        # Memorise.unlock('VstreamDownloaderLock')

        # fait une pause pour fermer le Dialog
        xbmc.sleep(900)

        # if download finish
        meta = {}
        meta['path'] = self.__fPath
        meta['size'] = TotDown
        meta['totalsize'] = iTotalSize

        if (TotDown == iTotalSize) and (iTotalSize > 10000):
            meta['status'] = 2
            try:
                cDb().update_download(meta)
                self.DIALOG.VSinfo(self.ADDON.VSlang(30003), self.__sTitle)
                self.RefreshDownloadList()
            except:
                pass
        else:
            meta['status'] = 0
            try:
                cDb().update_download(meta)
                self.DIALOG.VSinfo(self.ADDON.VSlang(30004), self.__sTitle)
                self.RefreshDownloadList()
            except:
                pass
            return

        # ok tout est bon on continu ou pas?
        # if Memorise.get('SimpleDownloaderQueue') == '1':
        if xbmcgui.Window(10101).getProperty('SimpleDownloaderQueue') == '1':
            print('Download suivant')
            tmp = cDownload()
            data = tmp.GetNextFile()
            tmp.StartDownload(data)

    def __updatedb(self, TotDown, iTotalSize):
        # percent 3 chiffre
        percent = '{0:.2f}'.format(min(100 * float(TotDown) / float(iTotalSize), 100))
        if percent in ['0.00', '10.00', '20.00', '30.00', '40.00', '50.00', '60.00', '70.00', '80.00', '90.00']:
            meta = {}
            meta['path'] = self.__fPath
            meta['size'] = TotDown
            meta['totalsize'] = iTotalSize
            meta['status'] = 1

            try:
                cDb().update_download(meta)
                self.RefreshDownloadList()
            except:
                pass

    def __stateCallBackFunction(self, iDownsize, iTotalSize):

        if self.__oDialog.isFinished():
            self.createProcessDialog()

        iPercent = int(float(iDownsize * 100) / iTotalSize)
        self.__oDialog.update(iPercent, self.__sTitle, self.__formatFileSize(float(iDownsize)) + '/' + self.__formatFileSize(iTotalSize))

        if (self.__oDialog.isFinished()) and not (self.__processIsCanceled):
            self.__processIsCanceled = True
            self.__oDialog.close()

    def run(self):

        try:
            # Recuperation url simple
            url = self.__sUrl.split('|')[0]
            # Recuperation des headers du lien
            headers = {}
            if len (self.__sUrl.split('|')) > 1:
                u = self.__sUrl.split('|')[1].split('&')
                for i in u:
                    headers[i.split('=')[0]] = i.replace(i.split('=')[0] + '=', '')

            # Rajout du user-agent si absent
            if not ('User-Agent' in headers):
                headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'

            req = urllib2.Request(url, None, headers)

            self.oUrlHandler = urllib2.urlopen(req, timeout=30)
            # self.__instance = repr(self)
            self.file = xbmcvfs.File(self.__fPath, 'w')
        except:
            VSlog('download error ' + self.__sUrl)
            self.DIALOG.VSinfo('Download error', self.ADDON.VSlang(30011))
            return

        # if not Memorise.lock('VstreamDownloaderLock'):
        #     self.DIALOG.VSinfo(self.ADDON.VSlang(30012), 'Download error')
        #     return

        if xbmc.getCondVisibility('Window.IsVisible(10151)'):
            self.DIALOG.VSinfo('Erreur', self.ADDON.VSlang(30012))
            return

        self._StartDownload()

    def __formatFileSize(self, iBytes):
        iBytes = int(iBytes)
        if (iBytes == 0):
            return '%.*f %s' % (2, 0, 'MB')

        return '%.*f %s' % (2, iBytes/(1024*1024.0), 'MB')

    def StopAll(self):

        self.processIsCanceled = True
        # Memorise.unlock('VstreamDownloaderLock')
        # Memorise.set('SimpleDownloaderQueue', '0')
        xbmcgui.Window(10101).setProperty('SimpleDownloaderQueue', '0')

        xbmcgui.Window(10101).setProperty('arret', '1')
        try:
            self.__oDialog.close()
        except:
            pass

        return

    def RefreshDownloadList(self):
        # print(xbmc.getInfoLabel('Container.FolderPath'))
        if 'function=getDownload' in xbmc.getInfoLabel('Container.FolderPath'):
            VSupdate()


class cDownload:
    DIALOG = dialog()
    ADDON = addon()

    def __init__(self):
        pass

    def __createDownloadFilename(self, sTitle):
        sTitle = re.sub(' +', ' ', sTitle)  # Vire double espace
        valid_chars = '-_.() abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
        filename = ''.join(c for c in sTitle if c in valid_chars)
        filename = filename.replace(' .', '.')
        if filename.startswith(' '):
            filename = filename[1:]
        # filename = filename.replace(' ', '_')  # pas besoin de ca, enfin pr moi en tout cas
        return filename

    def __formatFileSize(self, iBytes):
        iBytes = int(iBytes)
        if iBytes == 0:
            return '%.*f %s' % (2, 0, 'MB')

        return '%.*f %s' % (2, iBytes/(1024*1024.0), 'MB')

    def isDownloading(self):

        if not xbmc.getCondVisibility('Window.IsVisible(10151)'):
            return False
        return True

    def download(self, sDBUrl, sTitle, sDownloadPath, FastMode=False):

        if self.isDownloading():
            self.DIALOG.VSinfo('Erreur', self.ADDON.VSlang(30012))
            return False

        self.__sTitle = sTitle

        # resolve url
        from resources.lib.gui.hoster import cHosterGui
        oHoster = cHosterGui().checkHoster(sDBUrl)
        oHoster.setUrl(sDBUrl)
        aLink = oHoster.getMediaLink()

        if aLink[0]:
            sUrl = aLink[1]
        else:
            print('Lien non resolvable')
            self.DIALOG.VSinfo(self.ADDON.VSlang(30022), sTitle)
            return False

        if (not sUrl.startswith('http')) or sUrl.split('|')[0].endswith('.m3u8'):
            self.DIALOG.VSinfo(self.ADDON.VSlang(30022), sTitle)
            return False

        try:
            VSlog('Download ' + str(sUrl))

            # background download task
            if FastMode:
                cDownloadProgressBar(title=self.__sTitle, url=sUrl, Dpath=sDownloadPath, FastMode=True).start()
            else:
                cDownloadProgressBar(title=self.__sTitle, url=sUrl, Dpath=sDownloadPath).start()

            VSlog('Download Ok ' + sDownloadPath)

        except:
            self.DIALOG.VSinfo(self.ADDON.VSlang(30024), sTitle)
            VSlog('Unable to download')
            return False

        return True

    def __createTitle(self, sUrl, sTitle):

        sTitle = cUtil().FormatSerie(sTitle)
        sTitle = cUtil().CleanName(sTitle)

        aTitle = sTitle.rsplit('.')
        # Si deja extension
        if (len(aTitle) > 1):
            return sTitle

        # recherche d'une extension
        sUrl = sUrl.lower()

        m = re.search('(flv|avi|mp4|mpg|mpeg|mkv)', sUrl)
        if m:
            sTitle = sTitle + '.' + m.group(0)
        else:
            sTitle = sTitle + '.mp4'  # Si quedale on en prend une au pif

        return sTitle

    def getDownload(self):

        oGui = cGui()
        sPluginHandle = cPluginHandler().getPluginHandle()
        sPluginPath = cPluginHandler().getPluginPath()
        sItemUrl = '%s?site=%s&function=%s&title=%s' % (sPluginPath, SITE_IDENTIFIER, 'StartDownloadList', 'title')
        # meta = {'title': 'Démarrer la liste'}
        item = xbmcgui.ListItem('Démarrer la liste', iconImage='special://home/addons/plugin.video.mando/resources/art/download.png')

        # item.setInfo(type='Video', infoLabels=meta)
        # item.setProperty('Video', 'false')
        # item.setProperty('IsPlayable', 'false')

        xbmcplugin.addDirectoryItem(sPluginHandle, sItemUrl, item, isFolder=False)

        oOutputParameterHandler = cOutputParameterHandler()
        oGui.addDir(SITE_IDENTIFIER, 'StopDownloadList', self.ADDON.VSlang(30025), 'download.png', oOutputParameterHandler)

        oOutputParameterHandler = cOutputParameterHandler()
        oGui.addDir(SITE_IDENTIFIER, 'getDownloadList', self.ADDON.VSlang(30039), 'listes.png', oOutputParameterHandler)

        oOutputParameterHandler = cOutputParameterHandler()
        oGui.addDir(SITE_IDENTIFIER, 'CleanDownloadList', self.ADDON.VSlang(30040), 'download.png', oOutputParameterHandler)

        oGui.setEndOfDirectory()

    def CleanDownloadList(self):

        try:
            cDb().clean_download()
            self.DIALOG.VSinfo(self.ADDON.VSlang(30071))
        except:
            pass

        return

    def dummy(self):
        return

    def StartDownloadOneFile(self, meta=None):
        if meta is None:
            meta = []
        if not meta:
            meta = self.GetOnefile()

        xbmcgui.Window(10101).setProperty('SimpleDownloaderQueue', '0')
        self.StartDownload(meta)

    def ResetDownload(self):
        oInputParameterHandler = cInputParameterHandler()
        url = oInputParameterHandler.getValue('sUrl')
        meta = {}
        meta['url'] = url

        try:
            cDb().reset_download(meta)
            self.DIALOG.VSinfo(self.ADDON.VSlang(30071))
            VSupdate()
        except:
            pass

        return

    def ReadDownload(self):
        oInputParameterHandler = cInputParameterHandler()
        path = oInputParameterHandler.getValue('sPath')
        sTitle = oInputParameterHandler.getValue('sMovieTitle')

        oGuiElement = cGuiElement()
        oGuiElement.setSiteName(SITE_IDENTIFIER)
        oGuiElement.setMediaUrl(path)
        oGuiElement.setTitle(sTitle)
        # oGuiElement.getInfoLabel()

        oPlayer = cPlayer()
        # if not (sys.argv[1] == '-1'):
            # oPlayer.run(oGuiElement, sTitle, path)
        # else:
        oPlayer.clearPlayList()
        oPlayer.addItemToPlaylist(oGuiElement)
        oPlayer.startPlayer()

    def DelFile(self):
        oInputParameterHandler = cInputParameterHandler()
        path = oInputParameterHandler.getValue('sPath')

        oDialog = self.DIALOG.VSyesno(self.ADDON.VSlang(30074))
        if (oDialog == 1):
            meta = {}
            meta['url'] = ''
            meta['path'] = path

            try:
                cDb().del_download(meta)
                xbmcvfs.delete(path)
                self.DIALOG.VSinfo(self.ADDON.VSlang(30072))
                VSupdate()
            except:
                self.DIALOG.VSinfo(self.ADDON.VSlang(30073))

    def GetNextFile(self):
        row = cDb().get_download()

        for data in row:
            status = data[8]

            if status == '0':
                return data

        return None

    def GetOnefile(self):
        oInputParameterHandler = cInputParameterHandler()
        url = oInputParameterHandler.getValue('sUrl')

        meta = {}
        meta['url'] = url

        row = cDb().get_download(meta)

        if not (row):
            return None

        return row[0]

    def StartDownload(self, data):
        if not (data):
            return

        title = data[1]
        url = UnquotePlus(data[2])
        path = data[3]
        # thumbnail = UnquotePlus(data[4])
        # status = data[8]

        self.download(url, title, path)

    def StartDownloadList(self):
        self.DIALOG.VSinfo(self.ADDON.VSlang(30075))
        # Memorise.set('SimpleDownloaderQueue', '1')
        xbmcgui.Window(10101).setProperty('SimpleDownloaderQueue', '1')
        data = self.GetNextFile()
        self.StartDownload(data)

    def StopDownloadList(self):

        # oInputParameterHandler = cInputParameterHandler()
        # path = oInputParameterHandler.getValue('sPath')
        # status = oInputParameterHandler.getValue('sStatus')

        # WINDOW_PROGRESS = xbmcgui.Window(10101)
        # WINDOW_PROGRESS.close()
        # xbmcgui.Window(10101).setProperty('arret', '1')
        # xbmc.executebuiltin('Dialog.Close(%s, true)' % 10101)
        # xbmc.getCondVisibility('Window.IsActive(10101)')

        # thread actif
        if xbmcgui.Window(10101).getProperty('arret') == '0':
            xbmcgui.Window(10101).setProperty('arret', '1')
        # si bug
        else:
            cDownloadProgressBar().StopAll()

        # On remet tout les status a 0 ou 2
        cDb().cancel_download()

        VSupdate()

        return

    def getDownloadList(self):
        oGui = cGui()

        row = cDb().get_download()

        for data in row:

            title = data[1]
            url = UnquotePlus(data[2])
            path = data[3]
            # cat = data[4]
            thumbnail = UnquotePlus(data[5])
            # The url is unicode format ? Not managed yet
            try:
                thumbnail = str(thumbnail)
            except:
                thumbnail = ''

            size = data[6]
            totalsize = data[7]
            status = data[8]

            oOutputParameterHandler = cOutputParameterHandler()
            oOutputParameterHandler.addParameter('sUrl', url)
            oOutputParameterHandler.addParameter('sMovieTitle', title)
            oOutputParameterHandler.addParameter('sThumbnail', thumbnail)
            oOutputParameterHandler.addParameter('sPath', path)
            oOutputParameterHandler.addParameter('sStatus', status)

            if status == '0':
                sStatus = ''
            elif status == '1':
                sStatus = '[COLOR=red][En cours] [/COLOR]'
            elif status == '2':
                sStatus = '[COLOR=green][Fini] [/COLOR]'

            if size:
                sTitle = sStatus + title + ' (' + self.__formatFileSize(size) + '/' + self.__formatFileSize(totalsize) + ')'
            else:
                sTitle = sStatus + title

            oGuiElement = cGuiElement()

            if not thumbnail or thumbnail == 'False':
                thumbnail = 'mark.png'

            oGuiElement.setSiteName(SITE_IDENTIFIER)
            if status == '2':
                oGuiElement.setFunction('ReadDownload')
            else:
                # oGuiElement.setFunction('StartDownloadOneFile')  # marche pas a cause de fenetre xbmc
                oGuiElement.setFunction('ReadDownload')

            oGuiElement.setTitle(sTitle)
            oGuiElement.setIcon('download.png')
            oGuiElement.setMeta(0)
            oGuiElement.setThumbnail(thumbnail)

            oGui.createContexMenuDownload(oGuiElement, oOutputParameterHandler, status)

            oGui.addFolder(oGuiElement, oOutputParameterHandler)

        oGui.setEndOfDirectory()

        return

    def delDownload(self):

        oInputParameterHandler = cInputParameterHandler()
        url = oInputParameterHandler.getValue('sUrl')
        meta = {}
        meta['url'] = url
        meta['path'] = ''

        try:
            cDb().del_download(meta)
            self.DIALOG.VSinfo(self.ADDON.VSlang(30071))
            VSupdate()
        except:
            pass

        return

    def AddDownload(self, meta):

        sTitle = meta['title']
        sUrl = meta['url']

        # titre fichier
        sTitle = self.__createTitle(sUrl, sTitle)
        sTitle = self.__createDownloadFilename(sTitle)
        sTitle =  cGui().showKeyBoard(sTitle)

        if (sTitle != False and len(sTitle) > 0):

            # chemin de sauvegarde
            sPath2 = VSPath(self.ADDON.getSetting('download_folder'))

            dialog = xbmcgui.Dialog()
            sPath = dialog.browse(3, 'Downloadfolder', 'files', '', False, False, sPath2)

            if (sPath != ''):
                self.ADDON.setSetting('download_folder', sPath)
                sDownloadPath = VSPath(sPath + '%s' % (sTitle))

                if xbmcvfs.exists(sDownloadPath):
                    self.DIALOG.VSinfo(self.ADDON.VSlang(30082), sTitle)
                    return self.AddDownload(meta)
                else:
                    xbmcvfs.File(sDownloadPath, 'w')

                try:
                    VSlog(self.ADDON.VSlang(30083) + ' ' + str(sUrl))
                    meta['title'] = sTitle
                    meta['path'] = sDownloadPath

                    cDb().insert_download(meta)

                    return True

                except:
                    # print_exc()
                    self.DIALOG.VSinfo(self.ADDON.VSlang(30084), sTitle)
                    VSlog('Unable to download')

        return False

    def AddtoDownloadList(self):

        oInputParameterHandler = cInputParameterHandler()
        sMediaUrl = oInputParameterHandler.getValue('sMediaUrl')
        sFileName = oInputParameterHandler.getValue('sFileName')
        # sHosterIdentifier = oInputParameterHandler.getValue('sHosterIdentifier')
        # bGetRedirectUrl = oInputParameterHandler.getValue('bGetRedirectUrl')

        # if (bGetRedirectUrl == 'True'):
           # sMediaUrl = self.__getRedirectUrl(sMediaUrl)

        VSlog('Download ' + sMediaUrl)

        meta = {}
        meta['url'] = sMediaUrl
        meta['cat'] = oInputParameterHandler.getValue('sCat')
        meta['title'] = sFileName
        meta['icon'] = xbmc.getInfoLabel('ListItem.Art(thumb)')

        if (self.AddDownload(meta)):
            # telechargement direct ou pas?
            if not self.isDownloading():
                row = cDb().get_download(meta)
                if row:
                    self.StartDownloadOneFile(row[0])

        return

    def AddtoDownloadListandview(self):

        oInputParameterHandler = cInputParameterHandler()
        sMediaUrl = oInputParameterHandler.getValue('sMediaUrl')
        sFileName = oInputParameterHandler.getValue('sFileName')
        # sHosterIdentifier = oInputParameterHandler.getValue('sHosterIdentifier')

        VSlog('Download ' + sMediaUrl)

        meta = {}
        meta['url'] = sMediaUrl
        meta['cat'] = oInputParameterHandler.getValue('sCat')
        meta['title'] = sFileName
        meta['icon'] = xbmc.getInfoLabel('ListItem.Art(thumb)')

        if (self.AddDownload(meta)):
            # Si pas de telechargement en cours on lance le notre
            if not self.isDownloading():
                row = cDb().get_download(meta)
                if row:

                    title = row[0][1]
                    url = UnquotePlus(row[0][2])
                    path = row[0][3]
                    # thumbnail = UnquotePlus(row[0][4])
                    # status = row[0][8]
                    if (self.download(url, title, path, True) == True):  # Download in fastmode

                        # ok on attend un peu, et on lance le stream
                        tempo = 100
                        progress_ = progress().VScreate('Bufferisation')

                        while (tempo > 0):
                            # if canceled do nothing
                            if progress_.iscanceled():
                                break
                            progress_.VSupdate(progress_, 100)
                            tempo = tempo - 1
                            xbmc.sleep(500)

                        progress_.VSclose(progress_)

                        oGuiElement = cGuiElement()
                        oGuiElement.setSiteName(SITE_IDENTIFIER)
                        oGuiElement.setMediaUrl(path)
                        oGuiElement.setTitle(title)
                        # oGuiElement.getInfoLabel()

                        oPlayer = cPlayer()

                        # if not (sys.argv[1] == '-1'):
                            # oPlayer.run(oGuiElement, title, path)
                        # else:
                        oPlayer.clearPlayList()
                        oPlayer.addItemToPlaylist(oGuiElement)
                        oPlayer.startPlayer()

                    else:
                        self.DIALOG.VSinfo('Erreur', self.ADDON.VSlang(30085))
        return
