#!/usr/bin/python

from argparse import ArgumentParser
from pathlib import Path

MAILBOX_SUBDIRS = {"cur", "new", "tmp"}


def get_mailbox_from_dir(path: Path, mailboxes: list[Path]) -> None:
    """ Add mailboxes in a directory to a list.

    All directories below path are evaluated to have necessary subdirectories
    (see MAILBOX_SUBDIRS) to be counted as a mailbox directory.

    Parameters
    ----------
    path: Path
        The path to search in for mailbox directories
    mailboxes: list[Path]
        A list of paths to add mailboxes to
    """
    for current_path in path.iterdir():
        if current_path.is_dir() and current_path.name not in MAILBOX_SUBDIRS:
            subdirs = list(current_path.iterdir())
            if (
                MAILBOX_SUBDIRS & set(subdir.name for subdir in subdirs)
                and current_path not in mailboxes
            ):
                mailboxes.append(current_path)

            for subdir in subdirs:
                if subdir.name not in MAILBOX_SUBDIRS:
                    get_mailbox_from_dir(
                        path=current_path,
                        mailboxes=mailboxes,
                    )


def write_file(contents: str, output: Path) -> None:
    """Write a string to a file

    Parameters
    ----------
    contents: str
        The string to write
    output: Path
        The file path to write to
    """
    with open(output, "w") as f:
        print(contents, file=f)


def main(path: Path, output: Path) -> None:
    """Find mailbox directories in account directories and write them to file.

    The directories below path are considered to be account directories,
    containing mailboxes.
    The output is written to output and is compatible with mutt's mailboxes
    directive.


    Parameters
    ----------
    path: Path
        A directory below which directories are assumed to be account
        directories which contain mailboxes
    output: Path
        A file to which to write output to

    Raises
    ------
    RuntimeError
        If path does not exist
        or if path is not a directory
        or if path does not contain any directories
    """
    if not path.exists():
        raise RuntimeError(f"The input path '{path}' does not exist!")

    if not path.is_dir():
        raise RuntimeError(f"The input path '{path}' is not a directory!")

    accounts = [subdir for subdir in path.iterdir() if subdir.is_dir()]
    if len(accounts) == 0:
        raise RuntimeError(
            f"The path '{path}' does not contain any account directories!"
        )

    file_string = ""

    for account_dir in accounts:
        mailboxes: list[Path] = []
        mailboxes_string = "mailboxes "

        get_mailbox_from_dir(path=account_dir, mailboxes=mailboxes)

        for mailbox in mailboxes:
            mailbox_dir = str(mailbox).replace(
                str(account_dir.parent) + '/',
                '',
            )
            mailboxes_string += f" '+{mailbox_dir}'"

        if mailboxes:
            file_string += mailboxes_string + "\n"

    write_file(contents=file_string, output=output)


if __name__ == "__main__":
    parser = ArgumentParser(
        description="""
        Create 'mailboxes' entries for one or more directories.
        Each provided directory is
        """
    )
    parser.add_argument(
        "-o",
        "--output",
        default=Path("mailboxes.rc"),
        help="a file to write the mailboxes to (mailboxes.rc by default)",
        type=Path,
    )
    parser.add_argument(
        "path",
        default=Path("~/.local/state/mail/"),
        help="a directory to search in for mailbox directories",
        nargs="?",
        type=Path,
    )

    namespace = parser.parse_args()

    main(output=namespace.output, path=namespace.path)