from pathlib import Path
import fnmatch



class LoaderIgnore:
    __slots__ = (
        '__files', '__file_masks',
        '__paths', '__path_masks',
        '__env_names', '__env_name_masks',
    )

    def __init__(
        self,
        /,
        # file
        file: Path|str = None,
        files: list[Path|str] = None,
        file_mask: str = None,
        file_masks: list[str] = None,
        # path
        path: Path|str = None,
        paths: list[Path|str] = None,
        path_mask: str = None,
        path_masks: list[str] = None,
        # env
        env_name: str = None,
        env_names: list[str] = None,
        env_name_mask: str = None,
        env_name_masks: list[str] = None
    ):
        # file
        if files is None:
            files = []
        else:
            files = [Path(f) for f in files]

        if file is not None:
            file = Path(file)
            if file not in files:
                files.append(file)

        # file-mask
        if file_masks is None:
            file_masks = []

        if file_mask is not None and file_mask not in file_masks:
            file_masks.append(file_mask)

        # path
        if paths is None:
            paths = []
        else:
            paths = [Path(p).resolve() for p in paths]

        if path is not None:
            path = Path(path).resolve()
            if path not in paths:
                paths.append(path)

        # path-mask
        if path_masks is None:
            path_masks = []

        if path_mask is not None and path_mask not in path_masks:
            path_masks.append(path_mask)

        # env-name
        if env_names is None:
            env_names = []

        if env_name is not None and env_name not in env_names:
            env_names.append(env_name)

        # env-name-mask
        if env_name_masks is None:
            env_name_masks = []

        if env_name_mask is not None and env_name_mask not in env_name_masks:
            env_name_masks.append(env_name_mask)

        # init -----
        self.__files = files
        self.__file_masks = file_masks
        self.__paths = paths
        self.__path_masks = path_masks
        self.__env_names = env_names
        self.__env_name_masks = env_name_masks
        pass


    @property
    def files(self):
        return self.__files


    @property
    def file_masks(self):
        return self.__file_masks


    @property
    def paths(self):
        return self.__paths


    @property
    def path_masks(self):
        return self.__path_masks


    @property
    def env_names(self):
        return self.__env_names


    @property
    def env_name_masks(self):
        return self.__env_name_masks


    def is_ignored(
        self,
        /,
        path: Path = None,
        name: str = None
    ) -> bool:
        """
        Check if a file path or environment variable name should be ignored.

        :param path: file path
        :param name: env-var name
        :return:
        """

        # file path
        if path is not None:
            abs_path = path.resolve()
            file_name = path.name
            path_str = f'{path}'

            if (   any(
                    file_name == file.name
                    for file in self.__files
                )
                or any(
                    fnmatch.fnmatch(file_name, file_mask)
                    for file_mask in self.__file_masks
                )
                or any(
                    abs_path == path or path in abs_path.parents
                    for path in self.__paths
                )
                or any(
                    fnmatch.fnmatch(path_str, path_mask)
                    for path_mask in self.__path_masks
                )
            ):
                return True

        # env-var name
        if name is not None:
            if (   name in self.__env_names
                or any(
                    fnmatch.fnmatch(name, env_name_mask)
                    for env_name_mask in self.__env_name_masks
                )
            ):
                return True

        return False

    pass
