#!/usr/bin/env python3
import argparse
import json
import os
import re
import shutil
from typing import Callable
from fontTools.ttLib import TTFont
from source.py.utils import run

# Mapping of style names to weights
weight_map = {
    "Thin": "100",
    "ExtraLight": "200",
    "Light": "300",
    "Regular": "400",
    "Italic": "400",
    "SemiBold": "500",
    "Medium": "600",
    "Bold": "700",
    "ExtraBold": "800",
}


def format_fontsource_name(filename: str):
    match = re.match(r"MapleMono-(.*)\.(.*)$", filename)

    if not match:
        return None

    style = match.group(1)

    weight = weight_map[style.removesuffix("Italic") if style != "Italic" else "Italic"]
    suf = "italic" if "italic" in filename.lower() else "normal"

    new_filename = f"maple-mono-latin-{weight}-{suf}.{match.group(2)}"
    return new_filename


def format_woff2_name(filename: str):
    return filename.replace('.woff2', '-VF.woff2')


def rename_files(dir: str, fn: Callable[[str], str]):
    for filename in os.listdir(dir):
        if not filename.endswith(".woff") and not filename.endswith(".woff2"):
            continue
        new_name = fn(filename)
        if new_name:
            os.rename(os.path.join(dir, filename), os.path.join(dir, new_name))
            print(f"Renamed: {filename} -> {new_name}")


def parse_tag(args):
    """
    Parse the tag from the command line arguments.
    Format: v7.0[-beta3]
    """
    tag = args.tag

    if not tag.startswith("v"):
        tag = f"v{tag}"

    match = re.match(r"^v(\d+)\.(\d+)$", tag)
    if not match:
        raise ValueError(f"Invalid tag: {tag}, expected format: v7.0")

    major, minor = match.groups()
    # Remove leading zero from the minor version if necessary
    minor = str(int(minor))
    tag = f"v{major}.{minor}"

    if args.beta:
        tag += "-" if args.beta.startswith("beta") else "-beta" + args.beta

    return tag


def update_build_script_version(tag):
    with open("build.py", "r", encoding="utf-8") as f:
        content = f.read()
        f.close()
    content = re.sub(r'FONT_VERSION = ".*"', f'FONT_VERSION = "{tag}"', content)
    with open("build.py", "w", encoding="utf-8") as f:
        f.write(content)
        f.close()


def git_commit(tag, files):
    run(f"git add {' '.join(files)}")
    run(["git", "commit", "-m", f"Release {tag}"])
    run(f"git tag {tag}")
    print("Committed and tagged")

    run("git push origin")
    run(f"git push origin {tag}")
    print("Pushed to origin")


def format_font_map_key(key: int) -> str:
    formatted_key = f"{key:05X}"
    if formatted_key.startswith("0"):
        return formatted_key[1:]
    return formatted_key


def write_unicode_map_json(font_path: str, output: str):
    font = TTFont(font_path)
    font_map = {
        format_font_map_key(k): v
        for k, v in font.getBestCmap().items()
        if k is not None
    }
    with open(output, "w", encoding="utf-8") as f:
        f.write(json.dumps(font_map, indent=2))
    print(f"Write font map to {output}")
    font.close()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "tag",
        type=str,
        help="The tag to build the release for, format: 7.0 or v7.0",
    )
    parser.add_argument(
        "beta",
        nargs="?",
        type=str,
        help="Beta tag name, format: 3 or beta3",
    )
    parser.add_argument(
        "--dry",
        action="store_true",
        help="Dry run",
    )
    args = parser.parse_args()
    tag = parse_tag(args)
    # prompt and wait for user input
    choose = input(f"Tag {tag}? (Y or n) ")
    if choose != "" and choose.lower() != "y":
        print("Aborted")
        return
    update_build_script_version(tag)

    shutil.rmtree("./cdn", ignore_errors=True)
    target_fontsource_dir = "cdn/fontsource"
    run("python build.py --ttf-only --no-nerd-font --cn --no-hinted")
    run(f"ftcli converter ft2wf -f woff2 ./fonts/TTF -out {target_fontsource_dir}")
    run(f"ftcli converter ft2wf -f woff ./fonts/TTF -out {target_fontsource_dir}")
    rename_files(target_fontsource_dir, format_fontsource_name)
    print("Generate fontsource files")

    shutil.copytree("./fonts/CN", "./cdn/cn")
    print("Generate CN files")

    woff2_dir = 'woff2/var'
    if os.path.exists(target_fontsource_dir):
        shutil.rmtree(woff2_dir)
    run(f"ftcli converter ft2wf -f woff2 ./fonts/Variable -out {woff2_dir}")
    rename_files(woff2_dir, format_woff2_name)
    print("Update variable WOFF2")

    # write_unicode_map_json(
    #     "./fonts/TTF/MapleMono-Regular.ttf", "./resources/glyph-map.json"
    # )

    if args.dry:
        print("Dry run")
    else:
        git_commit(tag, ['build.py', 'woff2'])


if __name__ == "__main__":
    main()
