# -*- coding: utf-8 -*-
# plugin.video.alkoflix
# resources/lib/modules/thumbnails.py

import sqlite3 as database
from pathlib import Path
from datetime import datetime, timedelta
import xbmc, xbmcaddon, xbmcgui, xbmcvfs


def ls(string):
	try: return xbmcaddon.Addon().getLocalizedString(int(string))
	except: return str(string)


def logger(heading, function):
	try: xbmc.log('>> %s <<: %s' % (heading, function), 1)
	except: pass


def notification(line1, time=3000, sound=False):
	addon_info = xbmcaddon.Addon().getAddonInfo
	xbmcgui.Dialog().notification(addon_info('name'), line1, addon_info('icon'), time, sound)


def _delete_path(path):
	files_deleted, dirs_deleted = 0, 0
	try:
		if not path.exists(): return files_deleted, dirs_deleted
		if path.is_dir():
			for child in path.iterdir():
				child_files, child_dirs = _delete_path(child)
				files_deleted += child_files
				dirs_deleted += child_dirs
			try:
				path.rmdir()
				dirs_deleted += 1
			except Exception as e:
				logger('clear kodi thumbnails rmdir skipped', '%s | %s' % (path, e))
		else:
			try:
				path.unlink(missing_ok=True)
				files_deleted += 1
			except Exception as e:
				logger('clear kodi thumbnails file skipped', '%s | %s' % (path, e))
	except Exception as e:
		logger('clear kodi thumbnails path skipped', '%s | %s' % (path, e))
	return files_deleted, dirs_deleted


def _delete_folder_contents(folder):
	files_deleted, dirs_deleted = 0, 0
	try:
		if not folder.exists(): return files_deleted, dirs_deleted
		for child in folder.iterdir():
			child_files, child_dirs = _delete_path(child)
			files_deleted += child_files
			dirs_deleted += child_dirs
	except Exception as e:
		logger('clear kodi thumbnails folder skipped', '%s | %s' % (folder, e))
	return files_deleted, dirs_deleted


def _clear_textures_database(dbfile):
	dbcon = None
	try:
		if not dbfile.exists(): return False
		dbcon = database.connect(str(dbfile), isolation_level=None)
		dbcur = dbcon.cursor()
		dbcur.execute('''PRAGMA synchronous = OFF''')
		dbcur.execute('''PRAGMA journal_mode = OFF''')
		dbcur.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
		tables = {item[0] for item in dbcur.fetchall()}
		for table in ('sizes', 'texture', 'path'):
			if table in tables: dbcur.execute('DELETE FROM %s' % table)
		dbcon.commit()
		try: dbcur.execute('VACUUM')
		except Exception as e: logger('clear kodi thumbnails vacuum skipped', e)
		return True
	except Exception as e:
		logger('clear kodi thumbnails database failed', e)
		return False
	finally:
		try:
			if dbcon: dbcon.close()
		except: pass


def _delete_textures_database_files(dbfile):
	deleted = 0
	for suffix in ('', '-wal', '-shm', '-journal'):
		path = Path('%s%s' % (dbfile, suffix))
		try:
			if path.exists():
				path.unlink(missing_ok=True)
				deleted += 1
		except Exception as e:
			logger('clear kodi thumbnails db file skipped', '%s | %s' % (path, e))
	return deleted


def _textures_database_candidates():
	# Selon les versions/plateformes Kodi, special://database et
	# special://profile/Database peuvent pointer vers le même dossier. On vérifie
	# les deux afin d'éviter un faux nettoyage qui rate Textures13.db.
	candidates, seen = [], set()
	for special_path in ('special://database', 'special://profile/Database'):
		try:
			path = Path(xbmcvfs.translatePath(special_path), 'Textures13.db')
			key = str(path).lower()
			if key not in seen:
				seen.add(key)
				candidates.append(path)
		except Exception as e:
			logger('clear kodi thumbnails db candidate skipped', '%s | %s' % (special_path, e))
	return candidates


# Vide complètement le cache des vignettes Kodi et propose un redémarrage.
def clear_kodi_thumbnail_cache():
	progress_dialog = xbmcgui.DialogProgress()
	thumbs_folder = Path(xbmcvfs.translatePath('special://thumbnails'))
	dbfiles = _textures_database_candidates()
	try:
		progress_dialog.create('alkoFlix', 'Vidage du cache des vignettes Kodi...')
		progress_dialog.update(10, 'Nettoyage de Textures13.db...')
	except: pass
	database_cleared, db_files_deleted = False, 0
	for dbfile in dbfiles:
		if _clear_textures_database(dbfile): database_cleared = True
	try: progress_dialog.update(35, 'Suppression de Textures13.db...')
	except: pass
	for dbfile in dbfiles:
		db_files_deleted += _delete_textures_database_files(dbfile)
	try: progress_dialog.update(60, 'Suppression du dossier Thumbnails...')
	except: pass
	files_deleted, dirs_deleted = _delete_folder_contents(thumbs_folder)
	try:
		progress_dialog.update(100, 'Cache des vignettes Kodi vidé.')
		xbmc.sleep(700)
		progress_dialog.close()
	except: pass
	logger('clear kodi thumbnails done', 'database_cleared=%s | db_files_deleted=%s | files_deleted=%s | dirs_deleted=%s' % (database_cleared, db_files_deleted, files_deleted, dirs_deleted))
	text = 'Le cache des vignettes Kodi a été vidé : dossier Thumbnails nettoyé et Textures13.db vidé/supprimé quand Kodi le permet.[CR][CR]Un redémarrage de Kodi est nécessaire pour reconstruire correctement les nouvelles images.[CR][CR]Voulez-vous redémarrer Kodi maintenant ?'
	restart = xbmcgui.Dialog().yesno('alkoFlix', text, 'Plus tard', 'Redémarrer')
	if restart: xbmc.executebuiltin('RestartApp')
	else: notification('Cache des vignettes vidé. Redémarrez Kodi plus tard.', 4000)


# Vide le contenu du dossier temporaire Kodi et propose un redémarrage.
def clear_kodi_temp_cache():
	progress_dialog = xbmcgui.DialogProgress()
	temp_folder = Path(xbmcvfs.translatePath('special://temp'))
	try:
		progress_dialog.create('alkoFlix', 'Vidage du cache temporaire Kodi...')
		progress_dialog.update(25, 'Suppression du contenu du dossier temp...')
	except: pass
	files_deleted, dirs_deleted = _delete_folder_contents(temp_folder)
	try:
		progress_dialog.update(100, 'Cache temporaire Kodi vidé.')
		xbmc.sleep(700)
		progress_dialog.close()
	except: pass
	logger('clear kodi temp done', 'folder=%s | files_deleted=%s | dirs_deleted=%s' % (temp_folder, files_deleted, dirs_deleted))
	text = 'Le cache temporaire Kodi a été vidé : fichiers et sous-dossiers du dossier temp supprimés quand Kodi le permet.[CR][CR]Un redémarrage de Kodi est nécessaire pour finaliser correctement le nettoyage.[CR][CR]Voulez-vous redémarrer Kodi maintenant ?'
	restart = xbmcgui.Dialog().yesno('alkoFlix', text, 'Plus tard', 'Redémarrer')
	if restart: xbmc.executebuiltin('RestartApp')
	else: notification('Cache Kodi vidé. Redémarrez Kodi plus tard.', 4000)


def thumb_cleaner():
	current_date = datetime.date(datetime.utcnow())
	thumbs_folder = Path(xbmcvfs.translatePath('special://thumbnails'))
	dbfile = Path(xbmcvfs.translatePath('special://database'), 'Textures13.db')
	if not dbfile.exists(): return notification(ls(32575))
	item_list = []
	minimum_uses = 30
	days = xbmcgui.Dialog().numeric(0 , ls(33188), defaultt=str(minimum_uses))
	if not days: return notification(ls(33189))
	back_date = (current_date - timedelta(days=int(days))).strftime('%Y-%m-%d %H:%M:%S')
	dbcon = database.connect(str(dbfile), isolation_level=None)
	dbcur = dbcon.cursor()
	dbcur.execute('''PRAGMA synchronous = OFF''')
	dbcur.execute('''PRAGMA journal_mode = OFF''')
#	dbcur.execute(
#		"SELECT idtexture FROM sizes WHERE usecount < ? AND lastusetime < ?",
#		(minimum_uses, str(back_date))
#	)
	dbcur.execute("SELECT idtexture FROM sizes WHERE lastusetime < ?", (str(back_date), ))
	result = dbcur.fetchall()
	result_length = len(result)
	if not result_length > 0: return notification(ls(33190))
	progress_dialog = xbmcgui.DialogProgress()
	progress_dialog.create(ls(33191), '')
	progress_dialog.update(0, ls(33192))
	for count, item in enumerate(result):
		if progress_dialog.iscanceled(): break
		_id = item[0]
		dbcur.execute("SELECT cachedurl FROM texture WHERE id = ?", (_id, ))
		url = dbcur.fetchall()[0][0]
		path = thumbs_folder.joinpath(url)
		path.unlink(missing_ok=True)
		item_list.append((_id,))
		percent = int(count / result_length * 100)
		line = '[B]%s:[/B] %s[CR][B]%s:[/B] %02d - %s[CR][B]%s:[/B] %s'
		line = line % (ls(33197), result_length, ls(33198), count, str(path.name), ls(33199), str(path.parent))
		progress_dialog.update(max(1, percent), line)
	line = '%s %s[CR]%s[CR]%%s' % (ls(33193), result_length, ls(32577).replace('[B]', '').replace('[/B]', ''))
	progress_dialog.update(33, line % ls(33194))
	dbcur.executemany("DELETE FROM sizes WHERE idtexture = ?", item_list)
	progress_dialog.update(66, line % ls(33196))
	dbcur.executemany("DELETE FROM texture WHERE id = ?", item_list)
	progress_dialog.update(99, line % ls(33195))
	dbcon.commit()
	dbcur.execute("VACUUM")
	xbmc.sleep(1500)
	try: progress_dialog.close()
	except: pass
	return notification(ls(33200))
