from __future__ import annotations
import sys
from importlib.machinery import ModuleSpec, PathFinder
from importlib.machinery import all_suffixes as module_suffixes
from importlib.util import spec_from_file_location
from itertools import chain
from pathlib import Path

MAPPING: dict[str, str] = {'sankashti': 'D:\\downloads\\ekadashi-lib\\sankashti', 'venv': 'D:\\downloads\\ekadashi-lib\\venv'}
NAMESPACES: dict[str, list[str]] = {'venv': ['D:\\downloads\\ekadashi-lib\\venv'], 'venv.Include': ['D:\\downloads\\ekadashi-lib\\venv\\Include'], 'venv.Lib': ['D:\\downloads\\ekadashi-lib\\venv\\Lib'], 'venv.Scripts': ['D:\\downloads\\ekadashi-lib\\venv\\Scripts'], 'venv.Lib.site-packages': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages'], 'venv.Lib.site-packages.jaraco': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\jaraco'], 'venv.Lib.site-packages.docutils.parsers.rst.include': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\parsers\\rst\\include'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes.big-black': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes\\big-black'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes.big-white': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes\\big-white'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes.default': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes\\default'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes.medium-black': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes\\medium-black'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes.medium-white': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes\\medium-white'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes.small-black': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes\\small-black'], 'venv.Lib.site-packages.docutils.writers.s5_html.themes.small-white': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\docutils\\writers\\s5_html\\themes\\small-white'], 'venv.Lib.site-packages.id._internal': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\id\\_internal'], 'venv.Lib.site-packages.pytz.zoneinfo': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo'], 'venv.Lib.site-packages.pytz.zoneinfo.Africa': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Africa'], 'venv.Lib.site-packages.pytz.zoneinfo.America': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\America'], 'venv.Lib.site-packages.pytz.zoneinfo.Antarctica': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Antarctica'], 'venv.Lib.site-packages.pytz.zoneinfo.Arctic': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Arctic'], 'venv.Lib.site-packages.pytz.zoneinfo.Asia': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Asia'], 'venv.Lib.site-packages.pytz.zoneinfo.Atlantic': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Atlantic'], 'venv.Lib.site-packages.pytz.zoneinfo.Australia': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Australia'], 'venv.Lib.site-packages.pytz.zoneinfo.Brazil': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Brazil'], 'venv.Lib.site-packages.pytz.zoneinfo.Canada': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Canada'], 'venv.Lib.site-packages.pytz.zoneinfo.Chile': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Chile'], 'venv.Lib.site-packages.pytz.zoneinfo.Etc': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Etc'], 'venv.Lib.site-packages.pytz.zoneinfo.Europe': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Europe'], 'venv.Lib.site-packages.pytz.zoneinfo.Indian': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Indian'], 'venv.Lib.site-packages.pytz.zoneinfo.Mexico': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Mexico'], 'venv.Lib.site-packages.pytz.zoneinfo.Pacific': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\Pacific'], 'venv.Lib.site-packages.pytz.zoneinfo.US': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\US'], 'venv.Lib.site-packages.pytz.zoneinfo.America.Argentina': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\America\\Argentina'], 'venv.Lib.site-packages.pytz.zoneinfo.America.Indiana': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\America\\Indiana'], 'venv.Lib.site-packages.pytz.zoneinfo.America.Kentucky': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\America\\Kentucky'], 'venv.Lib.site-packages.pytz.zoneinfo.America.North_Dakota': ['D:\\downloads\\ekadashi-lib\\venv\\Lib\\site-packages\\pytz\\zoneinfo\\America\\North_Dakota']}
PATH_PLACEHOLDER = '__editable__.sankashti-0.1.0.finder' + ".__path_hook__"


class _EditableFinder:  # MetaPathFinder
    @classmethod
    def find_spec(cls, fullname: str, path=None, target=None) -> ModuleSpec | None:  # type: ignore
        # Top-level packages and modules (we know these exist in the FS)
        if fullname in MAPPING:
            pkg_path = MAPPING[fullname]
            return cls._find_spec(fullname, Path(pkg_path))

        # Handle immediate children modules (required for namespaces to work)
        # To avoid problems with case sensitivity in the file system we delegate
        # to the importlib.machinery implementation.
        parent, _, child = fullname.rpartition(".")
        if parent and parent in MAPPING:
            return PathFinder.find_spec(fullname, path=[MAPPING[parent]])

        # Other levels of nesting should be handled automatically by importlib
        # using the parent path.
        return None

    @classmethod
    def _find_spec(cls, fullname: str, candidate_path: Path) -> ModuleSpec | None:
        init = candidate_path / "__init__.py"
        candidates = (candidate_path.with_suffix(x) for x in module_suffixes())
        for candidate in chain([init], candidates):
            if candidate.exists():
                return spec_from_file_location(fullname, candidate)
        return None


class _EditableNamespaceFinder:  # PathEntryFinder
    @classmethod
    def _path_hook(cls, path) -> type[_EditableNamespaceFinder]:
        if path == PATH_PLACEHOLDER:
            return cls
        raise ImportError

    @classmethod
    def _paths(cls, fullname: str) -> list[str]:
        paths = NAMESPACES[fullname]
        if not paths and fullname in MAPPING:
            paths = [MAPPING[fullname]]
        # Always add placeholder, for 2 reasons:
        # 1. __path__ cannot be empty for the spec to be considered namespace.
        # 2. In the case of nested namespaces, we need to force
        #    import machinery to query _EditableNamespaceFinder again.
        return [*paths, PATH_PLACEHOLDER]

    @classmethod
    def find_spec(cls, fullname: str, target=None) -> ModuleSpec | None:  # type: ignore
        if fullname in NAMESPACES:
            spec = ModuleSpec(fullname, None, is_package=True)
            spec.submodule_search_locations = cls._paths(fullname)
            return spec
        return None

    @classmethod
    def find_module(cls, _fullname) -> None:
        return None


def install():
    if not any(finder == _EditableFinder for finder in sys.meta_path):
        sys.meta_path.append(_EditableFinder)

    if not NAMESPACES:
        return

    if not any(hook == _EditableNamespaceFinder._path_hook for hook in sys.path_hooks):
        # PathEntryFinder is needed to create NamespaceSpec without private APIS
        sys.path_hooks.append(_EditableNamespaceFinder._path_hook)
    if PATH_PLACEHOLDER not in sys.path:
        sys.path.append(PATH_PLACEHOLDER)  # Used just to trigger the path hook
