# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2023 David Seaward and contributors


import os
import subprocess
import sys
from importlib import metadata
from pathlib import Path
from typing import NoReturn


def invoke() -> None:
    args = sys.argv[1:]
    if not args or args[0] in ("--help", "--version"):
        print_metadata()
        sys.exit(0)
    elif len(args) < 2:
        print_metadata()
        sys.exit(1)
    else:
        verb, noun, *extra_args = args

        if verb == "show" and noun == "yourself":
            show_tardyon_folder()
            sys.exit(0)
        else:
            try:
                launch_tardyon_script(verb, noun, extra_args)
            except Exception as e:
                print(f"Script could not be invoked: {e}", file=sys.stderr)
                sys.exit(1)


def print_metadata() -> None:
    try:
        version = metadata.version("tardyon")
    except metadata.PackageNotFoundError:
        version = "unknown"

    metadata_msg = f'tardyon v{version}\nCall "tardyon VERB NOUN"'
    print(metadata_msg)


def show_tardyon_folder() -> None:
    target = Path.home() / ".local" / "bin" / "tardy"
    target.mkdir(parents=True, exist_ok=True)

    opened = False
    if sys.platform == "win32":
        try:
            os.startfile(target)
            opened = True
        except (AttributeError, OSError):
            pass
    elif sys.platform == "darwin":
        try:
            subprocess.run(["open", str(target)], check=True)
            opened = True
        except (subprocess.CalledProcessError, FileNotFoundError):
            pass
    else:
        try:
            subprocess.run(["xdg-open", str(target)], check=True)
            opened = True
        except (subprocess.CalledProcessError, FileNotFoundError):
            pass

    if not opened:
        print(target)


def launch_tardyon_script(verb: str, noun: str, args: list[str]) -> NoReturn:
    script_path = Path.home() / ".local" / "bin" / "tardy" / noun / f"{verb}.{noun}"

    if not script_path.exists():
        raise FileNotFoundError(f"{script_path} does not exist")
    if not os.access(script_path, os.X_OK):
        raise PermissionError(f"{script_path} is not executable")

    os.execv(str(script_path), [str(script_path)] + args)


if __name__ == "__main__":
    invoke()
