from tmdbhelper.lib.addon.thread import SafeThread
from jurialmunkey.ftools import cached_property


CRONJOB_POLL_TIME = 600


class CronJobMonitor(SafeThread):

    _poll_time = CRONJOB_POLL_TIME

    def __init__(self, parent, update_hour=0):
        SafeThread.__init__(self)
        self.exit = False
        self.update_hour = update_hour
        self.update_monitor = parent.update_monitor

    def _on_startup(self):
        self._do_recache_kodidb()
        self._do_trakt_authorization()

    def _on_poll(self):
        self._do_database_maintenance()
        self._do_delete_old_databases()
        self._do_library_update_check()
        self._do_delete_old_log_files()

    @cached_property
    def trakt_api(self):
        from tmdbhelper.lib.api.trakt.api import TraktAPI
        return TraktAPI()

    @cached_property
    def database_maintenance(self):
        from tmdbhelper.lib.script.method.maintenance import DatabaseMaintenance
        return DatabaseMaintenance()

    def _do_database_maintenance(self):
        self.database_maintenance.vacuum()

    def _do_delete_old_databases(self):
        self.database_maintenance.delete_legacy_folders()

    def _do_recache_kodidb(self):
        self.database_maintenance.recache_kodidb(notification=False)

    def _do_delete_old_log_files_in_folder(self, folder, regex, days=-7):
        from tmdbhelper.lib.files.futils import get_files_in_folder, get_write_path, delete_file
        from tmdbhelper.lib.addon.tmdate import get_todays_date
        date = get_todays_date(str_fmt="%Y-%m-%d", days=days)
        for file in get_files_in_folder(get_write_path(folder, make_dir=False), regex=regex):
            if file > date:
                continue
            delete_file(folder, file)

    def _do_delete_old_log_files(self):
        for folder, regex in (
            ('log_tagger', r".*\.json$"),
            ('log_library', r".*\.json$"),
            ('timer_report', r".*\.txt$"),
        ):
            self._do_delete_old_log_files_in_folder(folder, regex)

    def _do_trakt_authorization(self):
        from jurialmunkey.window import get_property
        self.trakt_api.authorize()
        self.update_monitor.waitForAbort(1)
        if not get_property('TraktIsAuth', is_type=float):
            return
        from tmdbhelper.lib.script.method.trakt import get_stats
        get_stats()

    def _do_library_update(self):
        from tmdbhelper.lib.addon.plugin import executebuiltin
        from tmdbhelper.lib.addon.tmdate import get_datetime_now, get_timedelta
        executebuiltin('RunScript(plugin.video.themoviedb.helper,library_autoupdate)')
        executebuiltin(f'Skin.SetString(TMDbHelper.AutoUpdate.LastTime,{get_datetime_now().strftime("%Y-%m-%dT%H:%M:%S")})')
        self.library_update_next += get_timedelta(hours=24)  # Set next update for tomorrow

    def _do_library_update_check(self):
        from jurialmunkey.parser import try_int
        from tmdbhelper.lib.addon.tmdate import convert_timestamp, get_datetime_now, get_timedelta, get_datetime_today, get_datetime_time, get_datetime_combine
        from tmdbhelper.lib.addon.plugin import get_setting, get_infolabel
        if not get_setting('library_autoupdate'):
            return
        self.library_update_next = get_datetime_combine(get_datetime_today(), get_datetime_time(try_int(self.update_hour)))
        self.library_update_last = get_infolabel('Skin.String(TMDbHelper.AutoUpdate.LastTime)')
        self.library_update_last = convert_timestamp(self.library_update_last) if self.library_update_last else None

        # If we've already updated the library today then set a new next update time for tomorrow
        if self.library_update_last and self.library_update_last > self.library_update_next:
            self.library_update_next += get_timedelta(hours=24)

        # If the next update timestamp has elapsed then we should update the library
        if get_datetime_now() > self.library_update_next:
            self._do_library_update()

    def run(self):
        self._on_startup()

        while not self.update_monitor.abortRequested() and not self.exit:
            self.update_monitor.waitForAbort(self._poll_time)
            self._on_poll()
