import subprocess
import time
from pathlib import Path

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import threading

SERVER = "server.py"

process = None


def start_server():
    global process

    print("\n==========================")
    print("Starting Explorer...")
    print("==========================")

    process = subprocess.Popen(
        ["python", SERVER]
    )

    print(f"Explorer PID: {process.pid}")

    

def watch_process():
    process.wait()
    print(f"\nExplorer exited (code {process.returncode})")

    threading.Thread(target=watch_process, daemon=True).start()


def stop_server():
    global process

    if process is None:
        return

    print("\nStopping Explorer...")

    process.terminate()

    try:
        process.wait(timeout=5)
    except Exception:
        process.kill()

    process = None

    print("Explorer stopped.")


class ReloadHandler(FileSystemEventHandler):

    def on_modified(self, event):

        print(
            event.event_type,
            event.src_path,
            event.is_directory
        )

        if event.is_directory:
            return

        path = Path(event.src_path)

        if path.suffix != ".py":
            return

        print("\n------------------------------")
        print(f"Changed : {path.name}")
        print(f"Full    : {path}")
        print("------------------------------")

        stop_server()

        print("Explorer fully stopped.")

        time.sleep(1)

        start_server()

        print("Explorer restart complete.")


if __name__ == "__main__":

    start_server()

    observer = Observer()

    observer.schedule(
        ReloadHandler(),
        ".",
        recursive=True
    )

    observer.start()

    print("\nWatching for changes...")

    try:

        while True:
            time.sleep(1)

    except KeyboardInterrupt:

        observer.stop()

        stop_server()

    observer.join()