import os
from packaging import version
import threading
import streamlit.watcher.path_watcher
import contextlib
import streamlit.elements.spinner

from ..common.patch import IS_WASM


class MockedThread(threading.Thread):
    def start(self):
        threading.current_thread = lambda: self
        try:
            self.run()
        except Exception as e:
            raise e


class WatcherMock:
    def __init__(
        self,
        path,
        callback,
        glob_pattern: str | None = None,
        allow_nonexistent: bool = False,
    ) -> None:
        pass

    def close(self) -> None:
        pass


class MockThreading:
    class Timer:
        def __init__(self, delay, cb):
            cb()

        def start(self):
            pass

    Lock = contextlib.nullcontext


def patch_streamlit():
    if IS_WASM:
        os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python"

        threading.Thread = MockedThread

        st_version = version.parse(streamlit.__version__)
        if st_version >= version.parse("1.32.0"):
            streamlit.watcher.path_watcher._is_watchdog_available = lambda: False
            streamlit.watcher.path_watcher.get_path_watcher_class = (
                lambda x: WatcherMock
            )
        else:
            streamlit.watcher.path_watcher.watchdog_available = False
            streamlit.watcher.path_watcher.EventBasedPathWatcher = WatcherMock

        streamlit.elements.spinner.threading = MockThreading
