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

from sh import git  # type: ignore
from typing import 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: OwnersData):
        files: Set[str] = set(
            git.bake("-C", args.path)
            .show(args.commit, pretty="", name_only=True, _tty_out=False)
            .splitlines()
        )

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

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

        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, files: Set[str], entry: MatchEntry) -> None:
        for f in files:
            if f == entry["exact"]:
                self.__add_entry(entry)

    def __partial_regex(self, files: Set[str], entry: MatchEntry) -> None:
        for f in files:
            if re.search(entry["partial_regex"], f):
                self.__add_entry(entry)

    def __regex(self, files: Set[str], entry: MatchEntry) -> None:
        for f in files:
            if re.fullmatch(entry["regex"], f):
                self.__add_entry(entry)

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


# The subcommand to get the reviewers.
def subcmd_reviewers(args: argparse.Namespace, data: 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()

    file = YamlLoader.load(args.path + "/OWNERS")
    args.func(args, file)


if __name__ == "__main__":
    main()
