import abc
import argparse

from typing import Dict
from typing import List
from typing import Optional
from typing import TextIO

class DocumentableMixin(metaclass=abc.ABCMeta):
    def __init__(
        self,
        description: Optional[str] = None,
        extra_sections: Optional[Dict[str, str]] = None,
        options_prolog: Optional[str] = None,
        options_epilog: Optional[str] = None,
    ) -> None: ...
    @property
    def description(self) -> Optional[str]: ...
    @property
    def parser(self) -> argparse.ArgumentParser: ...
    @parser.setter
    def parser(self, parser: argparse.ArgumentParser) -> None: ...
    @property
    def args(self) -> argparse.Namespace: ...
    @args.setter
    def args(self, args: argparse.Namespace) -> None: ...
    @property
    def argument_help(self) -> Dict[str, Optional[str]]: ...

class Application(DocumentableMixin):
    def __init__(
        self,
        name: str,
        version: str,
        author: Optional[str] = None,
        title: Optional[str] = None,
        description: Optional[str] = None,
        default_command: Optional[str] = None,
        add_help: bool = True,
        extra_sections: Optional[Dict[str, str]] = None,
        prolog: Optional[str] = None,
        epilog: Optional[str] = None,
        options_prolog: Optional[str] = None,
        options_epilog: Optional[str] = None,
        add_commands_section: bool = False,
    ) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def author(self) -> str: ...
    @property
    def version(self) -> str: ...
    @property
    def commands(self) -> List[Command]: ...
    @property
    def groups(self) -> List[Group]: ...
    def add_argument(self, *args, **kwargs) -> argparse.Action: ...
    def add(self, command: Command): ...
    def add_group(self, title: str) -> Group: ...
    def register(self): ...
    def handle(self) -> int: ...
    def run(
        self,
        args: Optional[List[str]] = None,
        namespace: Optional[argparse.Namespace] = None,
        exit_on_error: bool = True,
    ) -> int: ...
    def run_command(self, command: Command) -> int: ...
    def get_command(self, command_name: str) -> Command: ...
    def set_prolog(self, prolog: str) -> None: ...
    def set_epilog(self, epilog: str) -> None: ...
    def get_commands_text(self) -> str: ...
    def create_manpage(self) -> ManPage: ...
    def format_help(self) -> str: ...
    def print_help(self, file: Optional[TextIO] = None) -> None: ...

class Group:
    def __init__(
        self, title: Optional[str] = None, is_root: bool = False
    ) -> None: ...
    @property
    def application(self) -> Optional[Application]: ...
    @property
    def title(self) -> Optional[str]: ...
    @property
    def commands(self) -> List[Command]: ...
    @property
    def is_root(self) -> bool: ...
    def commands_as_actions(self) -> List[argparse.Action]: ...
    def set_app(self, app: Application) -> None: ...
    def add(self, command: Command) -> None: ...
    def __len__(self) -> int: ...

class Command(DocumentableMixin, metaclass=abc.ABCMeta):
    def __init__(
        self,
        name: str,
        title: Optional[str] = None,
        description: Optional[str] = None,
        add_help: bool = True,
        extra_sections: Optional[Dict[str, str]] = None,
        options_prolog: Optional[str] = None,
        options_epilog: Optional[str] = None,
    ) -> None: ...
    @property
    def application(self) -> Optional[Application]: ...
    @property
    def name(self) -> str: ...
    @property
    def title(self) -> Optional[str]: ...
    def add_argument(self, *args, **kwargs) -> None: ...
    def add_argument_group(self, *args, **kwargs) -> ArgumentGroup: ...
    def add_mutually_exclusive_group(
        self, *args, **kwargs
    ) -> MutuallyExclusiveGroup: ...
    def register(self) -> None: ...
    @abc.abstractmethod
    def handle(self) -> int: ...
    def create_manpage(self) -> ManPage: ...

class ManPage:
    def __init__(
        self,
        application_name: str,
        author: Optional[str] = "",
        command_name: Optional[str] = None,
        date: Optional[str] = None,
        title: Optional[str] = None,
        version: Optional[str] = "",
    ) -> None: ...
    @property
    def name(self) -> str: ...
    def metadata(self) -> List[str]: ...
    def preamble(self) -> List[str]: ...
    def header(self) -> str: ...
    def section_name(self) -> str: ...
    def add_section_synopsis(self, synopsis: str) -> None: ...
    def add_section(self, label: str, text: str) -> None: ...
    def groffify(self, text: str) -> str: ...
    def groffify_line(self, line: str) -> str: ...
    def export(self, output_dir: str) -> str: ...

class ArgumentGroup:
    def __init__(self, group: argparse._ArgumentGroup) -> None: ...
    @property
    def command(self) -> Optional[Command]: ...
    @command.setter
    def command(self, command: Command) -> None: ...
    def add_argument(self, *args, **kwargs) -> None: ...

class MutuallyExclusiveGroup:
    def __init__(self, meg: argparse._MutuallyExclusiveGroup) -> None: ...
    @property
    def command(self) -> Optional[Command]: ...
    @command.setter
    def command(self, command: Command) -> None: ...
    def add_argument(self, *args, **kwargs) -> None: ...

class Tester:
    def __init__(self, app: Application) -> None: ...
    @property
    def application(self) -> Application: ...
    def clear(self) -> None: ...
    def get_return_code(self) -> Optional[int]: ...
    def get_stdout(self) -> Optional[str]: ...
    def get_stderr(self) -> Optional[str]: ...
    def test_command(self, cmd_name: str, args: List[str]) -> None: ...
    def test_application(self, args: Optional[List[str]] = None) -> None: ...
