#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2025 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
# SPDX-License-Identifier: MIT
#
# Material Symbols mapper.
#
# This script downloads the Material Symbols codepoints and maps symbol names to Unicode character mappings.
#

import argparse
from pathlib import Path
from typing import Dict
import requests
from io import StringIO
from urllib.parse import quote


def download_file(url: str) -> bytes:
    """Download the file and return it."""
    response = requests.get(url)
    response.raise_for_status()  # Ensure we notice bad responses
    return response.content


def parse_codepoints_file(file_content: bytes) -> Dict[str, str]:
    """Parse the Material Symbols codepoints file and return name->codepoint mappings."""
    mappings = {}

    file_stream = StringIO(file_content.decode("utf-8"))
    for line in file_stream:
        line = line.strip()
        if not line or line.startswith("#"):
            continue

        # Format is: symbol_name codepoint
        parts = line.split(" ")
        if len(parts) != 2:
            continue

        name, codepoint = parts
        # Map names to codepoints
        try:
            mappings[name] = codepoint
        except ValueError:
            print(f"Warning: Invalid codepoint for symbol {name}: {codepoint}")

    return mappings


def validate_mappings(mappings: Dict[str, str]) -> bool:
    """Validate the mappings to ensure they're properly formatted."""
    valid = True
    for name, char in mappings.items():
        if not name.replace("_", "").isalnum():
            print(f"Warning: Invalid symbol name: {name}")
            valid = False
        if not char:
            print(f"Warning: Missing codepoint for: {name}")
            valid = False
    return valid


def to_camel_case(string: str) -> str:
    """Convert a string to camelCase."""
    words = string.replace("-", "_").split("_")
    for i, word in enumerate(words):
        words[i] = word if i == 0 else word.capitalize()
    return "".join(words)


def main():
    parser = argparse.ArgumentParser(description="Download Material Symbols")
    parser.add_argument("directory", type=Path, nargs='?', default=Path(__file__).parent / "../src", help="Path to src/ directory")

    args = parser.parse_args()

    base_url = "https://raw.githubusercontent.com/google/material-design-icons/refs/heads/master/variablefont"

    # Parse and validate mappings
    codepoints_url = (
        f"{base_url}/{quote('MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].codepoints')}"
    )
    mappings = parse_codepoints_file(download_file(codepoints_url))
    if not validate_mappings(mappings):
        print("Warning: Some mappings are invalid")

    # Generate a QML file with enums of symbol names
    with open(args.directory / "controls/qml/SymbolNames.qml", "w", encoding="utf-8") as f:
        f.write("// Copyright (C) 2025 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>\n")
        f.write("// SPDX-License-Identifier: MPL-2.0\n//\n")
        f.write("// This file is auto-generated by fetch-symbols, do not change it\n\n")
        f.write("pragma Singleton\n\n")
        f.write("Object {\n")
        for name, codepoint in mappings.items():
            prop_name = to_camel_case(f"symbol_{name}")
            f.write(f'    readonly property string {prop_name}: "{name}";\n')
        f.write("}\n")

    # Generate a JavaScript singleton with symbol name mappings
    with open(args.directory / "controls/qml/SymbolMappings.js", "w", encoding="utf-8") as f:
        # Qt's CMake integration only scans the first 128 bytes for this pragma.
        f.write(".pragma library\n\n")
        f.write("// Copyright (C) 2025 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>\n")
        f.write("// SPDX-License-Identifier: MPL-2.0\n//\n")
        f.write("// This file is auto-generated by fetch-symbols, do not change it\n\n")
        f.write("const symbolMappings = {\n")
        for name, codepoint in mappings.items():
            f.write(f'    "{name}": "\\u{codepoint}",\n')
        f.write("};\n\n")
        f.write("function getSymbolName(enumValue) {\n")
        f.write("    return symbolMappings[enumValue] || \"\";\n")
        f.write("}\n")

    # Generate a QML ListModel with symbol names and their corresponding symbol strings
    with open(args.directory / "gallery/qml/SymbolsModel.qml", "w", encoding="utf-8") as f:
        f.write("// Copyright (C) 2025 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>\n")
        f.write("// SPDX-License-Identifier: MPL-2.0\n//\n")
        f.write("// This file is auto-generated by fetch-symbols, do not change it\n\n")
        f.write("import QtQml.Models\n\n")
        f.write("ListModel {\n")
        for name, codepoint in mappings.items():
            f.write(f'\tListElement {{ name: "{name}"; codepoint: "\\u{codepoint}"; }}\n')
        f.write("}\n")

    print(f"Successfully generated mappings for {len(mappings)} symbols")
    print(f"Output written to: {args.directory.resolve()}")

    return 0


if __name__ == "__main__":
    exit(main())
