#!/bin/env python3
import argparse
import json
import os
import re
import yaml

from sh import git  # type: ignore
from typing import Dict, List, Set, TypedDict, Optional
from yaml.loader import SafeLoader

# A list of Gerrit users (email addresses).
#   Some OWNERS files have empty lists for 'owners' or 'reviewers', which
#   results in a None type for the value.
UsersList = Optional[List[str]]

# A YAML node with an extra line number.
class NumberedNode(TypedDict):
    line_number: int


class MatchEntry(TypedDict, total=False):
    suffix: str
    regex: str
    partial_regex: str
    exact: str
    owners: UsersList
    reviewers: UsersList


# The root YAML node of an OWNERS file
class OwnersData(NumberedNode, TypedDict, total=False):
    owners: UsersList
    reviewers: UsersList
    matchers: List[MatchEntry]


# A YAML loader that adds the start line number onto each node (for
# later linting support)
class YamlLoader(SafeLoader):
    def construct_mapping(
        self, node: yaml.nodes.Node, deep: bool = False
    ) -> NumberedNode:
        mapping: NumberedNode = super(YamlLoader, self).construct_mapping(
            node, deep=deep
        )  # type: ignore
        mapping["line_number"] = node.start_mark.line + 1
        return mapping

    # Load a file and return the OwnersData.
    @staticmethod
    def load(file: str) -> OwnersData:
        data: OwnersData
        with open(file, "r") as f:
            data = yaml.load(f, Loader=YamlLoader)
        return data


# Class to match commit information with OWNERS files.
class CommitMatch:
    def __init__(
        self, args: argparse.Namespace, owners: Dict[str, OwnersData]
    ):
        files: Set[str] = set(
            git.bake("-C", args.path)
            .show(args.commit, pretty="", name_only=True, _tty_out=False)
            .splitlines()
        )

        root_owners = owners[""]

        self.owners: Set[str] = set()
        self.reviewers: Set[str] = set()

        for f in files:
            path = f

            while True:
                path = os.path.dirname(path)

                if path not in owners:
                    if not path:
                        break
                    continue

                local_owners = owners[path]

                self.owners = self.owners.union(
                    local_owners.get("owners") or []
                )
                self.reviewers = self.reviewers.union(
                    local_owners.get("reviewers") or []
                )

                rel_file = os.path.relpath(f, path)

                for e in local_owners.get("matchers", None) or []:
                    if "exact" in e:
                        self.__exact(rel_file, e)
                    elif "partial_regex" in e:
                        self.__partial_regex(rel_file, e)
                    elif "regex" in e:
                        self.__regex(rel_file, e)
                    elif "suffix" in e:
                        self.__suffix(rel_file, e)

                if not path:
                    break

        self.reviewers = self.reviewers.difference(self.owners)

    def __add_entry(self, entry: MatchEntry) -> None:
        self.owners = self.owners.union(entry.get("owners") or [])
        self.reviewers = self.reviewers.union(entry.get("reviewers") or [])

    def __exact(self, file: str, entry: MatchEntry) -> None:
        if file == entry["exact"]:
            self.__add_entry(entry)

    def __partial_regex(self, file: str, entry: MatchEntry) -> None:
        if re.search(entry["partial_regex"], file):
            self.__add_entry(entry)

    def __regex(self, file: str, entry: MatchEntry) -> None:
        if re.fullmatch(entry["regex"], file):
            self.__add_entry(entry)

    def __suffix(self, file: str, entry: MatchEntry) -> None:
        if os.path.splitext(file)[1] == entry["suffix"]:
            self.__add_entry(entry)


# The subcommand to get the reviewers.
def subcmd_reviewers(
    args: argparse.Namespace, data: Dict[str, OwnersData]
) -> None:
    matcher = CommitMatch(args, data)

    # Print in `git push refs/for/branch%<reviewers>` format.
    if args.push_args:
        result = []
        for o in sorted(matcher.owners):
            # Gerrit uses 'r' for the required reviewers (owners).
            result.append(f"r={o}")
        for r in sorted(matcher.reviewers):
            # Gerrit uses 'cc' for the optional reviewers.
            result.append(f"cc={r}")
        print(",".join(result))
    # Print as Gerrit Add Reviewers POST format.
    # https://gerrit.openbmc.org/Documentation/rest-api-changes.html#add-reviewer
    else:

        def review_js(reviewer: str, state: str) -> str:
            return json.dumps(
                {
                    "reviewer": reviewer,
                    "state": state,
                    "notify": "NONE",
                    "notify_details": {"TO": {"accounts": [reviewer]}},
                }
            )

        for o in sorted(matcher.owners):
            print(review_js(o, "REVIEWER"))
        for r in sorted(matcher.reviewers):
            print(review_js(r, "CC"))


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-p", "--path", default=".", help="Root path to analyse"
    )
    subparsers = parser.add_subparsers()

    parser_reviewers = subparsers.add_parser(
        "reviewers", help="Generate List of Reviewers"
    )
    parser_reviewers.add_argument(
        "--push-args",
        default=False,
        action="store_true",
        help="Format as git push options",
    )
    parser_reviewers.add_argument(
        "--commit",
        default="HEAD",
        help="Commit(s) to match against",
    )
    parser_reviewers.set_defaults(func=subcmd_reviewers)

    args = parser.parse_args()

    owners_files = git.bake("-C", args.path)(
        "ls-files", "OWNERS", "**/OWNERS"
    ).splitlines()

    files = {}
    for f in owners_files:
        file = YamlLoader.load(os.path.join(args.path, f))
        dirpath = os.path.dirname(f)
        files[dirpath] = file

    args.func(args, files)


if __name__ == "__main__":
    main()
