#!/usr/bin/env python3

import argparse
from datetime import datetime
from pathlib import Path
import pwd
import subprocess
import shutil
import sys
from typing import Dict, List, Optional


def get_ids(username: Optional[str]) -> Dict[str, int]:
    """The uid and gid of given username."""
    try:
        user = pwd.getpwnam(username or "")
    except (KeyError, TypeError):
        return dict(uid=0, gid=0)
    return dict(uid=user.pw_uid, gid=user.pw_gid)


def parse_args(cont_cmd: str) -> List[str]:
    """Parse the commandline arguments."""

    app = argparse.ArgumentParser(prog=sys.argv[0], description="Docker/Podman wrapper")
    app.add_argument("command", type=str, help="The sub command that should be run")
    app.add_argument(
        "--username",
        type=str,
        help="Name of the systemd unit that is created.",
        default=None,
    )
    args, container_args = app.parse_known_args()
    ipv6_enable = ["--net", "slirp4netns:allow_host_loopback=true,enable_ipv6=true"]
    arguments = [args.command]
    for key, value in get_ids(args.username).items():
        if args.command == "build" and value:
            arguments.append(f"--build-arg={key.upper()}={value}")
        elif args.command == "run" and value:
            arguments.append("-e")
            arguments.append(f"{key.upper()}={value}")
        if args.command == "run" and cont_cmd == "podman":
            arguments += ipv6_enable
    return arguments + container_args


def get_container_cmd() -> List[str]:
    """Get the command of the container."""
    for cmd in ("podman", "docker"):
        cont_cmd = shutil.which(cmd)
        if cont_cmd:
            return [cont_cmd]
    raise ValueError("Docker or Podman must be installed on the system")


def get_container_name(argv: List[str], cmd: str) -> Optional[str]:
    """Get the container name of a container."""
    key_commands = {"build": "-t", "run": "--name"}
    for i, arg in enumerate(argv):
        if arg == key_commands.get(cmd):
            try:
                return argv[i + 1]
            except IndexError:
                return None
    return None


def write_command_to_disk(
    argv: List[str], to_capture: List[str] = ["run", "build"]
) -> None:
    """Write the current docker/podman command to disk.

    Parameters
    ==========

    argv: list[str]
        command line arguments
    to_capture: list[str]
        docker/podman sub commands that should be captured
    """
    container_dir = (Path("~") / ".freva_container_commands").expanduser()
    for cmd in to_capture:
        if cmd in argv:
            container_name = get_container_name(argv, cmd)
            container_dir.mkdir(exist_ok=True, parents=True)
            now = str(datetime.today())
            with open(container_dir / f"{container_name}.{cmd}", "w") as f_obj:
                f_obj.write(
                    f"container {container_name} created at {now} using command:\n\n"
                )
                f_obj.write(" ".join(command))


if __name__ == "__main__":

    container_cmd = get_container_cmd()
    command = container_cmd + parse_args(container_cmd[0])
    write_command_to_disk(command)
    try:
        subprocess.run(command, check=True)
    except subprocess.CalledProcessError:
        sys.exit(1)
