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


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

    :param base_path: A starting :py:class:`pathlib.Path`
    :param glob_pattern: Glob pattern to match. e.g `"*"` or `"**/*"`
    :param path_filter: A custom filter for more complex matching than can be provided by glob. Defaults to ``None``.
    :raises ValueError: input_base_path must exist and be a directory.
    :yield: The matched paths.
    """

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

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