#!/usr/bin/python3
import subprocess
import re
import os
import argparse
from collections import defaultdict
from enum import Enum
from glob import glob


class CheckType(Enum):
    NEW_FAMILY = 1
    MODIFIED_FAMILY = 2
    MODIFIED_FAMILY_METADATA = 3
    DESIGNER = 4


class CheckToken(Enum):
    NEW_FONT = 1
    DESIGNER = 2
    FONT_FAMILY = 3
    MODIFIED_FONTS = 4
    MODIFIED_METADATA = 5


def _parse_git_diff(diff_info: str) -> list[tuple[str, str]]:
    """
    '''
    A    ofl/mavenpro/MavenPro[wght].ttf
    M    ofl/mavenpro/METADATA.pb
    ''' -> [
        ("A", "ofl/mavenpro/MavenPro[wght].ttf"),
        ("M", "ofl/mavenpro/METADATA.pb")
    ]

    """
    parsed = re.findall(r"([A|M|D])(\t)(.*)", diff_info)
    return [(s, p) for s, _, p in parsed]


def directory_check_types(branch="origin/main"):
    git_diff_text = subprocess.run(
        ["git", "diff", branch, "--name-status"], capture_output=True
    ).stdout.decode("utf-8")
    git_diff = _parse_git_diff(git_diff_text)

    # Tokenize each directory git diff has reported
    directories_to_check = defaultdict(set)
    for state, path in git_diff:
        dirpath = (
            os.path.dirname(path)
            if path not in ("to_sandbox.txt", "to_production.txt")
            else path
        )

        dir_tokens = directories_to_check[dirpath]
        if path.startswith("catalog"):
            dir_tokens.add(CheckToken.DESIGNER)

        if path.startswith(("ofl", "ufl", "apache")):
            dir_tokens.add(CheckToken.FONT_FAMILY)

        if path.endswith((".ttf", ".otf")) and state == "A":
            dir_tokens.add(CheckToken.NEW_FONT)

        if path.endswith((".ttf", ".otf")) and (state == "M" or state == "D"):
            dir_tokens.add(CheckToken.MODIFIED_FONTS)

        if path.endswith((".txt", ".pb", ".html")) and state == "M":
            dir_tokens.add(CheckToken.MODIFIED_METADATA)

    # Set each directory's check type
    results = []
    for path, tokens in directories_to_check.items():
        if CheckToken.FONT_FAMILY in tokens:
            if CheckToken.MODIFIED_FONTS in tokens:
                results.append((path, CheckType.MODIFIED_FAMILY))
            elif CheckToken.MODIFIED_METADATA in tokens:
                results.append((path, CheckType.MODIFIED_FAMILY_METADATA))
            else:
                results.append((path, CheckType.NEW_FAMILY))
        if CheckToken.DESIGNER in tokens:
            results.append((path, CheckType.DESIGNER))
    return results


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--branch", default="origin/main", help="branch to compare current head against"
    )
    parser.add_argument(
        "--render", action="store_true", help="Check rendering of families only"
    )
    parser.add_argument("--pr-number", help="PR to output fontbakery report to")
    parser.add_argument("--pr-url-body", default="https://www.github.com/google/fonts/pull/%s")
    args = parser.parse_args()

    profile_test_file = os.path.join(os.path.dirname(__file__), "test_profiles.py")

    for directory, check_type in directory_check_types(args.branch):
        out = os.path.join("out", os.path.basename(directory))
        fonts = glob(os.path.join(directory, "*.ttf"))

        qa_cmd_prefix = ["gftools", "qa", "-f"] + fonts + ["-o", out]
        if args.pr_number:
            if not args.pr_url_body.endswith("/"):
                args.pr_url_body += "/"
            url = "%s%s" % (args.pr_url_body, args.pr_number)
            qa_cmd_prefix += ["--out-url", url]

        if args.render and check_type == CheckType.NEW_FAMILY:
            print(f"Rendering new family: {directory}")
            subprocess.run(qa_cmd_prefix + ["--render", "--imgs"])

        elif args.render and check_type == CheckType.MODIFIED_FAMILY:
            print(f"Rendering modified family: {directory}")
            subprocess.run(qa_cmd_prefix + ["-gfb", "--render", "--imgs"])
        
        # we only want args.render to do the above two conditions
        elif args.render: 
            continue

        elif check_type == CheckType.NEW_FAMILY:
            print(f"Checking new family: {directory}")
            subprocess.run(qa_cmd_prefix + ["--fontbakery"])

        elif check_type == CheckType.MODIFIED_FAMILY:
            print(f"Checking modified family: {directory}")
            subprocess.run(qa_cmd_prefix + ["-gfb", "--fontbakery", "--diffenator"])

        elif check_type == CheckType.MODIFIED_FAMILY_METADATA:
            print(f"Checking modified family metadata: {directory}")
            subprocess.run(qa_cmd_prefix + ["--fontbakery", "-o", out])

        elif check_type == CheckType.DESIGNER:
            print(f"Checking designer profile: {directory}")
            subprocess.run(["pytest", profile_test_file, directory])

        else:
            print(f"Skipping directory {directory}")


if __name__ == "__main__":
    main()
