import fsspec
from typing import Iterator
from typing import Tuple
from typing import List


def fs_walk(
    fs: fsspec.AbstractFileSystem,
    path: str,
    sort: bool = False,
) -> Iterator[Tuple[str, List[str], List[str]]]:
    """Return the list of files and directories in a directory.

    Args:
        fs: file system object
        path: path to the directory
        sort: if True, the list of files and directories is sorted
            alphabetically

    Returns:
        Iterator of (path, directories, files).
    """
    dirs, files = [], []
    try:
        listing = fs.ls(path, detail=True)
    except (FileNotFoundError, IOError):
        yield "", [], []
        return

    for info in listing:
        # each info name must be at least [path]/part , but here
        # we check also for names like [path]/part/
        pathname = info["name"].rstrip("/")
        name = pathname.rsplit("/", 1)[-1]
        if info["type"] == "directory" and pathname != path:
            # do not include "self" path
            dirs.append(pathname)
        else:
            files.append(name)

    def sort_sequence(sequence):
        """Sort the sequence if the user wishes."""
        return sorted(sequence) if sort else sequence

    dirs = sort_sequence(dirs)
    yield path, dirs, sort_sequence(files)

    for item in sort_sequence(dirs):
        yield from fs_walk(fs, item, sort=sort)