#!/usr/bin/env python3
"""Run `vi` on files whose contents grep `pattern`."""

import subprocess
from pathlib import Path
from typing import List

from libcli.basecli import BaseCLI

import srcs


class VipatCLI(BaseCLI):
    """Command line interface."""

    def init_parser(self) -> None:
        """Initialize argument parser."""

        self.parser = self.ArgumentParser(
            description="Run `vi` on files whose contents grep `pattern`.",
        )

    def add_arguments(self) -> None:
        """Add arguments to parser."""

        arg = self.parser.add_argument(
            "--vi",
            metavar="PROGRAM",
            default="vim",
            help="`vi` program",
        )
        self.add_default_to_help(arg)

        self.parser.add_argument(
            "-i",
            "--ignore-case",
            action="store_true",
            help="distinctions during pattern matching",
        )

        self.parser.add_argument(
            "pattern",
            metavar="PATTERN",
            nargs="?",  # hmm...
            help="regular expression to grep",
        )

        arg = self.parser.add_argument(
            "FILE",
            nargs="*",
            type=Path,
            help=str(
                "files to search/edit. Defaults to all SOURCE files "
                "found recursively in the current working directory"
            ),
        )

    def main(self) -> None:
        """Command line interface entry point (method)."""

        if not self.options.pattern:
            self.parser.error("Missing `PATTERN`.")

        files = self._get_matching_files()
        if files and len(files):
            self._edit(files)

    def _get_matching_files(self) -> List[str]:
        """Generate names of files whose contents match `pattern`."""

        args = [
            "/usr/bin/grep",
            "--files-with-matches",
            "--no-messages",
            "--devices=skip",
            "--directories=skip",
        ]
        if self.options.ignore_case:
            args += ["--ignore-case"]
        args += [self.options.pattern]
        args += [str(x) for x in self.options.FILE] if len(self.options.FILE) else srcs.srcs()

        self.debug(f"grep: `{args}`")
        grep = subprocess.run(args, capture_output=True, check=False, text=True)
        self.debug(f"grep: {grep.returncode!r}")

        return grep.stdout.splitlines()

    def _edit(self, files: list[str]) -> None:
        args = [self.options.vi]
        if self.options.ignore_case:
            args += ["-c", "set ignorecase"]
        args += ["+1", f"+/{str(self.options.pattern)}"]
        args += files

        self.debug(f"args: {args!r}")
        proc = subprocess.run(args, check=False)
        self.debug(f"{args[0]}: {proc.returncode!r}")


def main() -> None:
    """CLI entry point."""
    VipatCLI().main()


if __name__ == "__main__":
    main()
