#!/usr/bin/env python3

import argparse
from typing import List, Tuple
import sys
import os

try:
    from fontTools.ttLib import TTFont
except ImportError:
    print("Need fonttools package, do `pip3 install fonttools`")
    sys.exit(1)

# Fonts that are excluded from the license check
# Only add fonts that are known to be public domain or have a compatible license
_EXCLUDED_FONTS = {
    "OpenTypeTest GPOS One",
}

# Font name mapping to remove any style suffix
_FONT_NAME_MAP = {
    "Montserrat Medium": "Montserrat",
    "Montserrat SemiBold": "Montserrat",
    "Montserrat Bold": "Montserrat",
    "Source Han Sans SC Normal": "Source Han Sans SC",
}


def get_font_full_name(font_path: str) -> str:
    font = TTFont(font_path)
    name_records = font["name"].names
    fallback = None
    for record in name_records:
        if record.nameID == 1:  # ID 1 corresponds to the font family name and will be used if full name doesn't exists
            fallback = record.toStr()
        if record.nameID == 4:  # ID 4 corresponds to the full font name
            return record.toStr()
    return fallback


def list_intree_fonts(path: str) -> List[Tuple[str, str]]:
    fonts = []
    for root, _, files in os.walk(path):
        for file in files:
            if file.lower().endswith((".ttf", ".otf", ".woff", ".woff2")):
                font_path = os.path.join(root, file)
                font_name = get_font_full_name(font_path).strip()
                if font_name:
                    # Add a no-strict mode to ignore missing license files
                    fonts.append((font_path, font_name))
    return fonts


def has_intree_license(license_root_folder: str, font_name: str) -> bool:
    if font_name in _EXCLUDED_FONTS:
        return True

    # Prepare candidate folder names, ignoring casing
    candidates = {
        font_name.lower(),
        font_name.replace(" ", "_").lower(),
        font_name.replace(" ", "").lower(),
    }

    if font_name in _FONT_NAME_MAP:
        candidates.add(_FONT_NAME_MAP[font_name].lower())
        candidates.add(_FONT_NAME_MAP[font_name].replace(" ", "_").lower())
        candidates.add(_FONT_NAME_MAP[font_name].replace(" ", "").lower())

    # List all directories in the license_root_folder
    for entry in os.listdir(license_root_folder):
        entry_path = os.path.join(license_root_folder, entry)
        if os.path.isdir(entry_path):
            # Compare the directory name in lowercase with candidates
            if entry.lower() in candidates:
                # Check if the directory contains at least one file (ignoring subdirectories)
                for item in os.listdir(entry_path):
                    item_path = os.path.join(entry_path, item)
                    if os.path.isfile(item_path):
                        return True
    return False


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Verify font licenses")
    parser.add_argument(
        "--no-strict",
        action="store_true",
        help="Ignore missing license files",
        default=False,
    )
    args = parser.parse_args()

    SCRIPT_DIR = os.path.dirname(__file__)
    # List of font files in the tree
    fonts = list_intree_fonts(os.path.join(SCRIPT_DIR, ".."))
    has_font_without_license = False

    print("Verifying license for fonts:")
    for path, name in fonts:
        if has_intree_license(
            os.path.join(SCRIPT_DIR, "built_in_font", "font_license"), name
        ):
            print(f"  [OK] '{name}'")
        else:
            print(f"  [MISSING] '{name}' - {path}")
            has_font_without_license = True

    if has_font_without_license and not args.no_strict:
        sys.exit(1)
