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

#################################################################################################

import logging
import sqlite3
import sys
import traceback

import xbmc
import xbmcgui
import xbmcplugin
import xbmcvfs

from views import Playlist, VideoNodes
from utils import window, should_stop, settings, language

#################################################################################################

log = logging.getLogger("EMBY."+__name__)
KODI = xbmc.getInfoLabel('System.BuildVersion')[:2]

#################################################################################################

def video_database():
    db_version = {

        '17': 107,# Krypton
        '18': 110 # Leia
    }
    return xbmc.translatePath("special://database/MyVideos%s.db"
                              % db_version.get(KODI, "")).decode('utf-8')

def music_database():
    db_version = {

        '17': 60, # Krypton
        '18': 72  # Leia
    }
    return xbmc.translatePath("special://database/MyMusic%s.db"
                              % db_version.get(KODI, "")).decode('utf-8')

def texture_database():
    return xbmc.translatePath("special://database/Textures13.db").decode('utf-8')

def emby_database():
    return xbmc.translatePath("special://database/emby.db").decode('utf-8')

def kodi_commit():
    # verification for the Kodi video scan
    kodi_scan = window('emby_kodiScan') == "true"
    count = 0

    while kodi_scan:
        log.info("kodi scan is running, waiting...")

        if count == 10:
            log.info("flag still active, but will try to commit")
            window('emby_kodiScan', clear=True)

        elif should_stop() or xbmc.Monitor().waitForAbort(1):
            log.info("commit unsuccessful. sync terminating")
            return False

        kodi_scan = window('emby_kodiScan') == "true"
        count += 1

    return True


class DatabaseConn(object):
    # To be called as context manager - i.e. with DatabaseConn() as conn: #dostuff

    def __init__(self, database_file="video", commit_on_close=True, timeout=120):
        """
        database_file can be custom: emby, texture, music, video, :memory: or path to the file
        commit_mode set to None to autocommit (isolation_level). See python documentation.
        """
        self.db_file = database_file
        self.commit_on_close = commit_on_close
        self.timeout = timeout

    def __enter__(self):
        # Open the connection
        self.path = self._SQL(self.db_file)
        #traceback.print_stack()
        
        if settings('dblock') == "true":
            self.conn = sqlite3.connect(self.path, isolation_level=None, timeout=self.timeout)
        else:
            self.conn = sqlite3.connect(self.path, timeout=self.timeout)

        log.info("opened: %s - %s", self.path, id(self.conn))
        self.cursor = self.conn.cursor()

        if self.db_file == "emby":
            verify_emby_database(self.cursor)
            self.conn.commit()

        return self.cursor

    def _SQL(self, media_type):

        databases = {
            'emby': emby_database,
            'texture': texture_database,
            'music': music_database,
            'video': video_database
        }
        return databases[media_type]() if media_type in databases else self.db_file

    def __exit__(self, exc_type, exc_val, exc_tb):
        # Close the connection
        changes = self.conn.total_changes

        if exc_type is not None:
            # Errors were raised in the with statement
            log.error("Type: %s Value: %s", exc_type, exc_val)

        if self.commit_on_close == True and changes:
            log.info("number of rows updated: %s", changes)
            if self.db_file == "video":
                kodi_commit()
            self.conn.commit()
            log.info("commit: %s", self.path)

        log.info("closing: %s - %s", self.path, id(self.conn))
        self.cursor.close()
        self.conn.close()


def verify_emby_database(cursor):
    # Create the tables for the emby database
    # emby, view, version

    log.info("Verifying emby DB")
    cursor.execute(
        """CREATE TABLE IF NOT EXISTS emby(
        emby_id TEXT UNIQUE, media_folder TEXT, emby_type TEXT, media_type TEXT,
        kodi_id INTEGER, kodi_fileid INTEGER, kodi_pathid INTEGER, parent_id INTEGER,
        checksum INTEGER)""")
    cursor.execute(
        """CREATE TABLE IF NOT EXISTS view(
        view_id TEXT UNIQUE, view_name TEXT, media_type TEXT, kodi_tagid INTEGER, group_series TEXT)""")
    cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)")

    columns = cursor.execute("SELECT * FROM view")
    if 'group_series' not in [description[0] for description in columns.description]:
        log.info("Add missing column group_series")
        cursor.execute("ALTER TABLE view ADD COLUMN group_series 'TEXT'")


def db_reset():

    dialog = xbmcgui.Dialog()

    if not dialog.yesno(language(29999), language(33074)):
        return

    # first stop any db sync
    window('emby_online', value="reset")
    window('emby_shouldStop', value="true")
    count = 10
    while window('emby_dbScan') == "true":
        log.info("Sync is running, will retry: %s..." % count)
        count -= 1
        if count == 0:
            dialog.ok(language(29999), language(33085))
            return
        xbmc.sleep(1000)

    # Clean up the playlists
    Playlist().delete_playlists()

    # Clean up the video nodes
    VideoNodes().deleteNodes()

    # Wipe the kodi databases
    log.warn("Resetting the Kodi video database.")
    with DatabaseConn('video') as cursor:
        cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
        rows = cursor.fetchall()
        for row in rows:
            tablename = row[0]
            if tablename != "version":
                cursor.execute("DELETE FROM " + tablename)

    if settings('enableMusic') == "true":
        log.warn("Resetting the Kodi music database.")
        with DatabaseConn('music') as cursor:         
            cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
            rows = cursor.fetchall()
            for row in rows:
                tablename = row[0]
                if tablename != "version":
                    cursor.execute("DELETE FROM " + tablename)

    # Wipe the emby database
    log.warn("Resetting the Emby database.")
    with DatabaseConn('emby') as cursor:    
        cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
        rows = cursor.fetchall()
        for row in rows:
            tablename = row[0]
            if tablename != "version":
                cursor.execute("DELETE FROM " + tablename)
        cursor.execute('DROP table IF EXISTS emby')
        cursor.execute('DROP table IF EXISTS view')
        cursor.execute("DROP table IF EXISTS version")

    # Offer to wipe cached thumbnails
    if dialog.yesno(language(29999), language(33086)):
        log.warn("Resetting all cached artwork")
        # Remove all existing textures first
        import artwork
        artwork.Artwork().delete_cache()

    # reset the install run flag
    settings('SyncInstallRunDone', value="false")

    # Remove emby info
    resp = dialog.yesno(language(29999), language(33087))
    if resp:
        import connectmanager
        # Delete the settings
        addondir = xbmc.translatePath(
                   "special://profile/addon_data/plugin.video.emby/").decode('utf-8')
        dataPath = "%ssettings.xml" % addondir
        xbmcvfs.delete(dataPath)
        connectmanager.ConnectManager().clear_data()

    dialog.ok(heading=language(29999), line1=language(33088))
    xbmc.executebuiltin('RestartApp')
    try:
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem())
    except:
        pass