#!/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", []):
            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:
        for o in sorted(matcher.owners):
            print(json.dumps({"reviewer": o, "state": "REVIEWER"}))
        for r in sorted(matcher.reviewers):
            print(json.dumps({"reviewer": r, "state": "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",
        action=argparse.BooleanOptionalAction,
        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()
