import sqlite3
from _thread import get_ident, allocate_lock
import xbmcvfs
import xbmc
import xbmcgui
from helper import utils
from . import emby_db, video_db, music_db, texture_db, addon_db, common_db

DBConnectionsRW = {}
DBConnectionsRO = {}

def DBVacuum():
    xbmc.executebuiltin('Dialog.Close(addoninformation)')
    ProgressBar = xbmcgui.DialogProgressBG()
    ProgressBar.create(utils.Translate(33199), utils.Translate(33436))
    TotalItems = len(utils.DatabaseFiles) / 100
    Index = 1

    for DBID, DBFile in list(utils.DatabaseFiles.items()):
        ProgressBar.update(int(Index / TotalItems), utils.Translate(33436), str(DBID))

        if 'version' in DBID:
            continue

        if not xbmcvfs.exists(DBFile):
            continue

        xbmc.log(f"EMBY.database.dbio: ---> DBVacuum: {DBID}", 0) # LOGDEBUG

        if DBID not in DBConnectionsRW:
            globals()["DBConnectionsRW"][DBID] = [None, None, allocate_lock()]

        globals()["DBConnectionsRW"][DBID][2].acquire()
        globals()["DBConnectionsRW"][DBID][0] = sqlite3.connect(DBFile, timeout=999999)
        globals()["DBConnectionsRW"][DBID][1] = DBConnectionsRW[DBID][0].cursor()

        if DBID == "music":
            DBConnectionsRW[DBID][1].execute("DELETE FROM removed_link")
            DBConnectionsRW[DBID][1].close()
            DBConnectionsRW[DBID][0].commit()

        try:
            DBConnectionsRW[DBID][0].execute("PRAGMA journal_mode=OFF")
        except:
            xbmc.log(f"EMBY.database.dbio: Journalmode cannot be changed to OFF ---> DBVacuum: {DBID}", 0) # LOGDEBUG

        DBConnectionsRW[DBID][0].execute("PRAGMA page_size=65536")
        DBConnectionsRW[DBID][0].execute("VACUUM")

        try:
            DBConnectionsRW[DBID][0].execute("PRAGMA journal_mode=WAL")
        except:
            xbmc.log(f"EMBY.database.dbio: Journalmode cannot be changed to WAL ---> DBVacuum: {DBID}", 0) # LOGDEBUG

        DBConnectionsRW[DBID][0].execute("ANALYZE")
        DBConnectionsRW[DBID][0].close()
        globals()["DBConnectionsRW"][DBID][0] = None
        globals()["DBConnectionsRW"][DBID][1] = None
        globals()["DBConnectionsRW"][DBID][2].release()
        xbmc.log(f"EMBY.database.dbio: ---< DBVacuum: {DBID}", 0) # LOGDEBUG
        Index += 1

    ProgressBar.close()
    del ProgressBar

def DBOpenRO(DBID, TaskId):
    DBIDThreadID = f"{DBID}{TaskId}{get_ident()}"
    xbmc.log(f"EMBY.database.dbio: ---> DBRO: {DBIDThreadID}", 0) # LOGDEBUG
    globals()["DBConnectionsRO"][DBIDThreadID] = [sqlite3.connect(f"file:{utils.DatabaseFiles[DBID]}?mode=ro", uri=True, timeout=999999, check_same_thread=False), None]
    DBConnectionsRO[DBIDThreadID][1] = DBConnectionsRO[DBIDThreadID][0].cursor()

    if DBID == 'video':
        return video_db.VideoDatabase(DBConnectionsRO[DBIDThreadID][1])

    if DBID == 'music':
        return music_db.MusicDatabase(DBConnectionsRO[DBIDThreadID][1])

    if DBID == 'texture':
        return texture_db.TextureDatabase(DBConnectionsRO[DBIDThreadID][1])

    if DBID == 'addon':
        return addon_db.AddonDatabase(DBConnectionsRO[DBIDThreadID][1])

    if DBID in ('epg', 'tv'):
        return common_db.CommonDatabase(DBConnectionsRO[DBIDThreadID][1])

    return emby_db.EmbyDatabase(DBConnectionsRO[DBIDThreadID][1])

def DBCloseRO(DBID, TaskId):
    DBIDThreadID = f"{DBID}{TaskId}{get_ident()}"

    if DBIDThreadID in DBConnectionsRO:
        DBConnectionsRO[DBIDThreadID][1].close()
        DBConnectionsRO[DBIDThreadID][0].close()
        globals()["DBConnectionsRO"][DBIDThreadID] = [None, None]
        xbmc.log(f"EMBY.database.dbio: ---< DBRO: {DBIDThreadID}", 0) # LOGDEBUG
    else:
        xbmc.log(f"EMBY.database.dbio: DBIDThreadID not found {DBIDThreadID}", 3) # LOGERROR

def DBOpenRW(Databases, TaskId, SQLs):
    DBIDs = Databases.split(",")

    for DBID in DBIDs:
        if DBID in utils.DatabaseFiles:
            if DBID not in DBConnectionsRW:
                globals()["DBConnectionsRW"][DBID] = [None, None, allocate_lock()]

            xbmc.log(f"EMBY.database.dbio: ---> DBRW: {DBID}/{TaskId}/{DBConnectionsRW[DBID][2].locked()}", 0) # LOGDEBUG
            globals()["DBConnectionsRW"][DBID][2].acquire()
            globals()["DBConnectionsRW"][DBID][0] = sqlite3.connect(utils.DatabaseFiles[DBID], timeout=999999, check_same_thread=False)
            globals()["DBConnectionsRW"][DBID][1] = DBConnectionsRW[DBID][0].cursor()
            DBConnectionsRW[DBID][0].execute("PRAGMA journal_mode=WAL")
            DBConnectionsRW[DBID][0].execute("PRAGMA secure_delete=false")

            if DBID == 'video':
                SQLs[DBID] = video_db.VideoDatabase(DBConnectionsRW[DBID][1])
            elif DBID == 'music':
                SQLs[DBID] = music_db.MusicDatabase(DBConnectionsRW[DBID][1])
            elif DBID == 'texture':
                SQLs[DBID] = texture_db.TextureDatabase(DBConnectionsRW[DBID][1])
            elif DBID == 'addon':
                SQLs[DBID] = addon_db.AddonDatabase(DBConnectionsRW[DBID][1])
            elif DBID in ('tv', 'epg'):
                SQLs[DBID] = common_db.CommonDatabase(DBConnectionsRW[DBID][1])
            else:
                SQLs["emby"] = emby_db.EmbyDatabase(DBConnectionsRW[DBID][1])

            xbmc.log(f"EMBY.database.dbio: ---> DBRW: {DBID}", 0) # LOGDEBUG

def DBCloseRW(Databases, TaskId, SQLs):
    DBIDs = Databases.split(",")

    for DBID in DBIDs:
        if DBID in DBConnectionsRW:
            DBConnectionsRW[DBID][1].close() # curser close
            changes = DBConnectionsRW[DBID][0].total_changes

            if changes:
                DBConnectionsRW[DBID][0].commit()

            DBConnectionsRW[DBID][0].close() # db close

            if DBID in ('video', 'music', 'texture', 'epg', 'tv', 'addon'):
                SQLs[DBID] = None
            else:
                SQLs["emby"] = None

            globals()["DBConnectionsRW"][DBID][0] = None
            globals()["DBConnectionsRW"][DBID][1] = None
            globals()["DBConnectionsRW"][DBID][2].release()
            xbmc.log(f"EMBY.database.dbio: ---< DBRW: {DBID} / {changes} / {TaskId} rows updated on db close", 0) # LOGDEBUG
