#!/usr/bin/env python3

import argparse
import re
import subprocess

REMOTE_TYPES = [
    {
        # github
        "match": re.compile(r'git@github.com:(?P<username>[\w\.-]+)/(?P<project>[\w\.-]+).git'),
        "format-branch": lambda g, b: f"https://github.com/{g['username']}/{g['project']}/tree/{b}/",
        "format-commit": lambda g, c: f"https://github.com/{g['username']}/{g['project']}/commit/{c}/",
    },
    {
        # gitea
        "match": re.compile(r'(?P<gituser>[\w\.-]+)@(?P<host>[\w\.-]+):(?P<username>[\w\.-]+)/(?P<project>[\w\.-]+).git'),
        "format-branch": lambda g, b: f"https://{g['host']}/{g['username']}/{g['project']}/src/branch/{b}/",
        "format-commit": lambda g, c: f"https://{g['host']}/{g['username']}/{g['project']}/commit/{c}/",
    },
]

def get_remote_branch():
    s = subprocess.run(["git", "status", "--porcelain", "-uno", "-b", "--no-ahead-behind"], capture_output=True, text=True)

    git_status_branch_info = s.stdout.splitlines()[0][3:].split()[0]

    branches = git_status_branch_info.split("...")

    if len(branches) != 2:
        raise Exception("no branch name found")

    local_branch, remote_branch = branches

    remote, branch = remote_branch.split("/")

    return {
        "remote": remote,
        "branch": branch,
    }

def get_remote_url(remote):
    s = subprocess.run(["git", "remote", "get-url", remote], capture_output=True, text=True)

    remote_url = s.stdout.strip()

    return remote_url

def get_last_commit():
    s = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True)

    commit = s.stdout.strip()

    return commit

def main():
    parser = argparse.ArgumentParser(
        prog='git-show-link',
    )

    parser.add_argument("--branch", dest="display_branch", action='store_true', help="Display link to branch, instead to commit")

    args = parser.parse_args()

    r = get_remote_branch()

    remote_url = get_remote_url(r["remote"])

    for remote_type in REMOTE_TYPES:
        m = remote_type["match"].match(remote_url)

        if m is None:
            continue

        g = m.groupdict()

        if args.display_branch:
            print(remote_type["format-branch"](g, r["branch"]))
        else:
            commit = get_last_commit()
            print(remote_type["format-commit"](g, commit))
        break


if __name__ == "__main__":
    main()