import logging
import time
import os

from Config import config

if config.debug and config.action == "main":
    try:
        import watchdog
        import watchdog.observers
        import watchdog.events
        logging.debug("Watchdog fs listener detected, source code autoreload enabled")
        enabled = True
    except Exception as err:
        logging.debug("Watchdog fs listener could not be loaded: %s" % err)
        enabled = False
else:
    enabled = False


class DebugReloader:
    def __init__(self, paths=None):
        if not paths:
            paths = ["src", "plugins", config.data_dir + "/__plugins__"]
        self.log = logging.getLogger("DebugReloader")
        self.last_chaged = 0
        self.callbacks = []
        if enabled:
            self.observer = watchdog.observers.Observer()
            event_handler = watchdog.events.FileSystemEventHandler()
            event_handler.on_modified = event_handler.on_deleted = self.onChanged
            event_handler.on_created = event_handler.on_moved = self.onChanged
            for path in paths:
                if not os.path.isdir(path):
                    continue
                self.log.debug("Adding autoreload: %s" % path)
                self.observer.schedule(event_handler, path, recursive=True)
            self.observer.start()

    def addCallback(self, f):
        self.callbacks.append(f)

    def onChanged(self, evt):
        path = evt.src_path
        ext = path.rsplit(".", 1)[-1]
        if ext not in ["py", "json"] or "Test" in path or time.time() - self.last_chaged < 1.0:
            return False
        self.last_chaged = time.time()
        if os.path.isfile(path):
            time_modified = os.path.getmtime(path)
        else:
            time_modified = 0
        self.log.debug("File changed: %s reloading source code (modified %.3fs ago)" % (evt, time.time() - time_modified))
        if time.time() - time_modified > 5:  # Probably it's just an attribute change, ignore it
            return False

        time.sleep(0.1)  # Wait for lock release
        for callback in self.callbacks:
            try:
                callback()
            except Exception as err:
                self.log.exception(err)

    def stop(self):
        if enabled:
            self.observer.stop()
            self.log.debug("Stopped autoreload observer")

watcher = DebugReloader()
