from pathlib import Path
from typing import Optional
from typing import Callable
from typing import Generator


def collect_paths(
    input_base_path: Path,
    glob_pattern: str,
    path_filter: Optional[Callable[[Path], bool]] = None,
) -> Generator[Path, None, None]:
    """
    Collect paths, and apply a filter

    Parameters
    ----------
    input_base_path : Path
        A starting Path
    glob_pattern : str
        Glob pattern to match. e.g "*" or "**/*"
    path_filter : Optional[Callable[[Path], bool]], optional
        A custom filter for more complex matching than can be provided by glob, by default None

    Yields
    -------
    Generator[Path, None, None]
        The matched Paths.

    Raises
    ------
    ValueError
        input_base_path must exist and be a directory.
    """

    # default content filter.
    def pass_through(_path_in: Path):
        return True

    if path_filter is None:
        path_filter = pass_through
    if not input_base_path.is_dir():
        raise ValueError(f"{input_base_path} - Not a directory or does not exist.")
    paths_in = input_base_path.glob(glob_pattern)
    for path_in in paths_in:
        if path_filter(path_in):
            yield path_in