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

import xbmcvfs

from resources.lib.handler.inputParameterHandler import cInputParameterHandler
from resources.lib.util import QuotePlus, Unquote
from resources.lib.comaddon import dialog, addon, VSlog, VSPath

SITE_IDENTIFIER = 'cDb'
SITE_NAME = 'DB'

try:
    from sqlite3 import dbapi2 as sqlite
    VSlog('SQLITE 3 as DB engine for db')
except:
    from pysqlite2 import dbapi2 as sqlite
    VSlog('SQLITE 2 as DB engine for db')

class cDb:

    DB = 'special://home/userdata/addon_data/plugin.video.mando/vstream.db'
    # important seul xbmcvfs peux lire le special
    try:
        REALDB = VSPath(DB).decode('utf-8')
    except AttributeError:
        REALDB = VSPath(DB)

    def __init__(self):

        try:
            if not xbmcvfs.exists(self.DB):
                self.db = sqlite.connect(self.REALDB)
                self.db.row_factory = sqlite.Row
                self.dbcur = self.db.cursor()
                self._create_tables()
                return
        except:
            VSlog('Error: Unable to write to %s' % self.REALDB)
            pass

        try:
            self.db = sqlite.connect(self.REALDB)
            self.db.row_factory = sqlite.Row
            self.dbcur = self.db.cursor()
        except:
            VSlog('Error: Unable to access to %s' % self.REALDB)
            pass

    def __del__(self):
        ''' Cleanup db when object destroyed '''
        try:
            self.dbcur.close()
            self.db.close()
        except Exception:
            pass

    def _create_tables(self):

        # sql_create2 = 'DROP TABLE history'

        ''' Create table '''
        sql_create = "CREATE TABLE IF NOT EXISTS history ("\
                        "addon_id integer PRIMARY KEY AUTOINCREMENT, "\
                        "title TEXT, "\
                        "disp TEXT, "\
                        "icone TEXT, "\
                        "isfolder TEXT, "\
                        "level TEXT, "\
                        "lastwatched TIMESTAMP "", "\
                        "UNIQUE(title)"\
                        ");"
        self.dbcur.execute(sql_create)

        sql_create = "CREATE TABLE IF NOT EXISTS resume ("\
                        "addon_id integer PRIMARY KEY AUTOINCREMENT, "\
                        "title TEXT, "\
                        "hoster TEXT, "\
                        "point TEXT, "\
                        "UNIQUE(title, hoster)"\
                        ");"
        self.dbcur.execute(sql_create)

        sql_create = "CREATE TABLE IF NOT EXISTS watched ("\
                        "addon_id integer PRIMARY KEY AUTOINCREMENT, "\
                        "title TEXT, "\
                        "site TEXT, "\
                        "UNIQUE(title, site)"\
                        ");"
        self.dbcur.execute(sql_create)

        sql_create = "CREATE TABLE IF NOT EXISTS favorite ("\
                        "addon_id integer PRIMARY KEY AUTOINCREMENT, "\
                        "title TEXT, "\
                        "siteurl TEXT, "\
                        "site TEXT, "\
                        "fav TEXT, "\
                        "cat TEXT, "\
                        "icon TEXT, "\
                        "fanart TEXT, "\
                        "UNIQUE(title, site)"\
                        ");"
        self.dbcur.execute(sql_create)

        sql_create = "CREATE TABLE IF NOT EXISTS download ("\
                        "addon_id integer PRIMARY KEY AUTOINCREMENT, "\
                        "title TEXT, "\
                        "url TEXT, "\
                        "path TEXT, "\
                        "cat TEXT, "\
                        "icon TEXT, "\
                        "size TEXT,"\
                        "totalsize TEXT, "\
                        "status TEXT, "\
                        "UNIQUE(title, path)"\
                        ");"
        self.dbcur.execute(sql_create)

        VSlog('Table initialized')

    # Ne pas utiliser cette fonction pour les chemins
    def str_conv(self, data):
        if isinstance(data, str):
            # Must be encoded in UTF-8
            try:
                data = data.decode('utf8')
            except AttributeError:
                pass
        import unicodedata
        data = unicodedata.normalize('NFKD', data).encode('ascii', 'ignore')
        data = data.decode('string-escape')  # ATTENTION: provoque des bugs pour les chemins a cause du caractere '/'

        return data

    # ***********************************
    #   History fonctions
    # ***********************************

    def insert_history(self, meta):

        # title = Unquote(meta['title']).decode('ascii', 'ignore')
        title = self.str_conv(Unquote(meta['title']))
        disp = meta['disp']
        icon = 'icon.png'

        try:
            ex = 'INSERT INTO history (title, disp, icone) VALUES (?, ?, ?)'
            self.dbcur.execute(ex, (title, disp, icon))
            self.db.commit()
            VSlog('SQL INSERT history Successfully')
        except Exception as e:
            if 'UNIQUE constraint failed' in e.message:
                ex = "UPDATE history set title = '%s', disp = '%s', icone= '%s' WHERE title = '%s'" % (title, disp, icon, title)
                self.dbcur.execute(ex)
                self.db.commit()
                VSlog('SQL UPDATE history Successfully')
            VSlog('SQL ERROR INSERT')
            pass

    def get_history(self):
        sql_select = 'SELECT * FROM history'

        try:
            self.dbcur.execute(sql_select)
            # matchedrow = self.dbcur.fetchone()
            matchedrow = self.dbcur.fetchall()
            return matchedrow
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return None

    def del_history(self):
        from resources.lib.gui.gui import cGui
        oGui = cGui()
        oInputParameterHandler = cInputParameterHandler()
        if oInputParameterHandler.exist('searchtext'):
            sql_delete = "DELETE FROM history WHERE title = '%s'" % (oInputParameterHandler.getValue('searchtext'))
        else:
            sql_delete = 'DELETE FROM history;'

        try:
            self.dbcur.execute(sql_delete)
            self.db.commit()
            dialog().VSinfo(addon().VSlang(30041))
            oGui.updateDirectory()
            return False, False
        except Exception:
            VSlog('SQL ERROR DELETE')
            return False, False

    # ***********************************
    #   Watched fonctions
    # ***********************************

    def insert_watched(self, meta):
        title = meta['title']
        if not title:
            return

        site = QuotePlus(meta['site'])
        ex = 'INSERT INTO watched (title, site) VALUES (?, ?)'
        self.dbcur.execute(ex, (title, site))
        try:
            self.db.commit()
            VSlog('SQL INSERT watched Successfully')
        except Exception:
            VSlog('SQL ERROR INSERT')
            pass

    def get_watched(self, meta):
        title = meta['title']
        if not title:
            return None

        sql_select = "SELECT * FROM watched WHERE title = '%s'" % title

        try:
            self.dbcur.execute(sql_select)
            # matchedrow = self.dbcur.fetchone()
            matchedrow = self.dbcur.fetchall()

            if matchedrow:
                return 1
            return 0
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return None

    def del_watched(self, meta):
        title = meta['title']
        if not title:
            return

        sql_select = "DELETE FROM watched WHERE title = '%s'" % title
        try:
            self.dbcur.execute(sql_select)
            self.db.commit()
            return False, False
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return False, False

    # ***********************************
    #   Resume fonctions
    # ***********************************

    def insert_resume(self, meta):
        title = self.str_conv(meta['title'])
        site = QuotePlus(meta['site'])
        # hoster = meta['hoster']
        point = meta['point']
        ex = "DELETE FROM resume WHERE hoster = '%s'" % site
        self.dbcur.execute(ex)
        ex = 'INSERT INTO resume (title, hoster, point) VALUES (?, ?, ?)'
        self.dbcur.execute(ex, (title, site, point))

        try:
            self.db.commit()
            VSlog('SQL INSERT resume Successfully')
        except Exception:
            VSlog('SQL ERROR INSERT')
            pass

    def get_resume(self, meta):
        # title = self.str_conv(meta['title'])
        site = QuotePlus(meta['site'])

        sql_select = "SELECT * FROM resume WHERE hoster = '%s'" % site

        try:
            self.dbcur.execute(sql_select)
            # matchedrow = self.dbcur.fetchone()
            matchedrow = self.dbcur.fetchall()
            return matchedrow
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return None

    def del_resume(self, meta):
        site = QuotePlus(meta['site'])

        sql_select = "DELETE FROM resume WHERE hoster = '%s'" % site

        try:
            self.dbcur.execute(sql_select)
            self.db.commit()
            return False, False
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return False, False


    # ***********************************
    #   Bookmark fonctions
    # ***********************************

    def insert_bookmark(self, meta):

        title = self.str_conv(meta['title'])
        siteurl = QuotePlus(meta['siteurl'])

        try:
            sIcon = meta['icon'].decode('UTF-8')
        except:
            sIcon = meta['icon']

        try:
            ex = 'INSERT INTO favorite (title, siteurl, site, fav, cat, icon, fanart) VALUES (?, ?, ?, ?, ?, ?, ?)'
            self.dbcur.execute(ex, (title, siteurl, meta['site'], meta['fav'], meta['cat'], sIcon, meta['fanart']))

            self.db.commit()

            dialog().VSinfo(addon().VSlang(30042), meta['title'])
            VSlog('SQL INSERT favorite Successfully')
        except Exception as e:
            if 'UNIQUE constraint failed' in e.message:
                dialog().VSinfo(addon().VSlang(30043), meta['title'])
            VSlog('SQL ERROR INSERT')
            pass

    def get_bookmark(self):

        sql_select = 'SELECT * FROM favorite'

        try:
            self.dbcur.execute(sql_select)
            # matchedrow = self.dbcur.fetchone()
            matchedrow = self.dbcur.fetchall()
            return matchedrow
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return None

    def del_bookmark(self, sSiteUrl='', sMovieTitle='', sCat = '', sAll = False):
        
        sql_delete = None

        # Tous supprimer
        if sAll:
            sql_delete = 'DELETE FROM favorite;'

        # Supprimer un bookmark selon son titre
        elif sMovieTitle:
            siteUrl = QuotePlus(sSiteUrl)
            title = self.str_conv(sMovieTitle)
            title = title.replace("'", r"''")
            sql_delete = "DELETE FROM favorite WHERE siteurl = '%s' AND title = '%s'" % (siteUrl, title)

        # Supprimer un bookmark selon son url
        elif sSiteUrl:
            siteUrl = QuotePlus(sSiteUrl)
            sql_delete = "DELETE FROM favorite WHERE siteurl = '%s'" % siteUrl

        # Supprimer toute une catégorie
        elif sCat:
            sql_delete = "DELETE FROM favorite WHERE cat = '%s'" % sCat


        if sql_delete:
            from resources.lib.gui.gui import cGui
            try:
                self.dbcur.execute(sql_delete)
                self.db.commit()
                update = self.db.total_changes
                
                if not update and sSiteUrl and sMovieTitle:
                    # si pas trouvé, on essaie sans le titre, seulement l'URL
                    return self.del_bookmark(sSiteUrl)
                    
                dialog().VSinfo(addon().VSlang(30044))
                cGui().updateDirectory()
                return False, False
            except Exception:
                VSlog('SQL ERROR EXECUTE')
                return False, False

    # ***********************************
    #   Download fonctions
    # ***********************************

    def insert_download(self, meta):

        title = self.str_conv(meta['title'])
        url = QuotePlus(meta['url'])
        sIcon = QuotePlus(meta['icon'])
        sPath = meta['path']

        ex = 'INSERT INTO download (title, url, path, cat, icon, size, totalsize, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
        self.dbcur.execute(ex, (title,url, sPath,meta['cat'],sIcon, '', '', 0))

        try:
            self.db.commit()
            VSlog('SQL INSERT download Successfully')
            dialog().VSinfo(addon().VSlang(30042), meta['title'])
        except Exception:
            VSlog('SQL ERROR INSERT')
            pass

    def get_download(self, meta=''):

        if meta == '':
            sql_select = 'SELECT * FROM download'
        else:
            url = QuotePlus(meta['url'])
            sql_select = "SELECT * FROM download WHERE url = '%s' AND status = '0'" % url

        try:
            self.dbcur.execute(sql_select)
            matchedrow = self.dbcur.fetchall()
            return matchedrow
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return None

    def clean_download(self):

        sql_select = "DELETE FROM download WHERE status = '2'"

        try:
            self.dbcur.execute(sql_select)
            self.db.commit()
            return False, False
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return False, False

    def reset_download(self, meta):

        url = QuotePlus(meta['url'])
        sql_select = "UPDATE download SET status = '0' WHERE status = '2' AND url = '%s'" % url

        try:
            self.dbcur.execute(sql_select)
            self.db.commit()
            return False, False
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return False, False

    def del_download(self, meta):

        if len(meta['url']) > 1:
            url = QuotePlus(meta['url'])
            sql_select = "DELETE FROM download WHERE url = '%s'" % url
        elif len(meta['path']) > 1:
            path = meta['path']
            sql_select = "DELETE FROM download WHERE path = '%s'" % path
        else:
            return

        try:
            self.dbcur.execute(sql_select)
            self.db.commit()
            return False, False
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return False, False

    def cancel_download(self):
        sql_select = "UPDATE download SET status = '0' WHERE status = '1'"
        try:
            self.dbcur.execute(sql_select)
            self.db.commit()
            return False, False
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return False, False

    def update_download(self, meta):

        path = meta['path']
        size = meta['size']
        totalsize = meta['totalsize']
        status = meta['status']

        sql_select = "UPDATE download set size = '%s', totalsize = '%s', status= '%s' WHERE path = '%s'" % (size, totalsize, status, path)

        try:
            self.dbcur.execute(sql_select)
            self.db.commit()
            return False, False
        except Exception:
            VSlog('SQL ERROR EXECUTE')
            return False, False
