#!/usr/bin/env python3
#
# This is a debugging tool that takes as input a bunch of different
# emoji data sources, and outputs a convenient HTML table that can be
# used to sanity-check the differences between these different data
# sources' decisions about what names to provide to each Unicode
# codepoint.
import os
import sys
from typing import Any

import orjson

TOOLS_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
ZULIP_PATH = os.path.dirname(TOOLS_DIR)
sys.path.append(ZULIP_PATH)

from tools.setup.emoji.emoji_names import EMOJI_NAME_MAPS
from tools.setup.emoji.emoji_setup_utils import emoji_is_supported, get_emoji_code

UNIFIED_REACTIONS_FILE = os.path.join(
    ZULIP_PATH, "zerver", "management", "data", "unified_reactions.json"
)
EMOJI_DATA_FILE = os.path.join(ZULIP_PATH, "node_modules", "emoji-datasource-google", "emoji.json")
EMOJI_CACHE = os.path.join(ZULIP_PATH, "static", "generated", "emoji")
OUTPUT_FILE = os.path.join(EMOJI_CACHE, "emoji_names_table.html")

# Emoji sets that we currently support.
EMOJISETS = ["google", "twitter"]

with open(EMOJI_DATA_FILE, "rb") as fp:
    EMOJI_DATA = orjson.loads(fp.read())
with open(UNIFIED_REACTIONS_FILE, "rb") as fp:
    UNIFIED_REACTIONS_MAP = orjson.loads(fp.read())

EMOJI_IMAGE_TEMPLATE = """
    <img class="emoji" src="images-{emojiset}-64/{emoji_code}.png" title={emojiset}>
"""

TABLE_ROW_TEMPLATE = """
    <tr>
        <td class="new-sorting-info">{sorting_info}</td>
        <td class="emoji-code">{emoji_code}</td>
        <td class="emoji-images">{images_html}</td>
        <td class="zulip-emoji-names">{zulip_names}</td>
        <td class="iamcal-emoji-names">{iamcal_names}</td>
        <td class="gemoji-emoji-names">{gemoji_names}</td>
        <td class="unicode-name">{unicode_name}</td>
    </tr>
"""

EMOJI_LISTING_TEMPLATE = """
<html>
    <head>
        <style>
            {table_css}
        </style>
        <title>Zulip emoji names</title>
    </head>
    <body>
        <table>
            <thead>
                <tr>
                    <th class="new-sorting-info">Category</th>
                    <th class="emoji-code">Emoji code</th>
                    <th class="emoji-images">Images</th>
                    <th class="zulip-emoji-names">Zulip</th>
                    <th class="iamcal-emoji-names">Iamcal (Slack)</th>
                    <th class="gemoji-emoji-names">Gemoji (unordered)</th>
                    <th class="unicode-name">Unicode</th>
                </tr>
            </thead>
            <tbody>
                {tbody}
            </tbody>
        </table>
    </body>
</html>
"""

TABLE_CSS = """
    .emoji {
        height: 35px;
        width: 35px;
        position: relative;
        margin-top: -7px;
        vertical-align: middle;
        top: 3px;
    }

    .emoji-images {
        width: 200px;
    }

    table, td, th {
        border: 1px solid black;
        border-collapse: collapse;
    }

    td, th {
        height: 40px;
        text-align: center;
    }

    .google {
        background-image: url('sheet-google-64.png') !important;
    }

    .twitter {
        background-image: url('sheet-twitter-64.png') !important;
    }
"""

SORTED_CATEGORIES = [
    "Smileys & Emotion",
    "People & Body",
    "Animals & Nature",
    "Food & Drink",
    "Activities",
    "Travel & Places",
    "Objects",
    "Symbols",
    "Flags",
    "Skin Tones",
]

emoji_code_to_zulip_names: dict[str, str] = {}
emoji_code_to_iamcal_names: dict[str, str] = {}
emoji_code_to_gemoji_names: dict[str, str] = {}
emoji_collection: dict[str, list[dict[str, Any]]] = {category: [] for category in SORTED_CATEGORIES}


def generate_emoji_code_to_emoji_names_maps() -> None:
    # Prepare gemoji names map.
    reverse_unified_reactions_map: dict[str, list[str]] = {}
    for name in UNIFIED_REACTIONS_MAP:
        emoji_code = UNIFIED_REACTIONS_MAP[name]
        if emoji_code in reverse_unified_reactions_map:
            reverse_unified_reactions_map[emoji_code].append(name)
        else:
            reverse_unified_reactions_map[emoji_code] = [name]

    for emoji_code in reverse_unified_reactions_map:
        emoji_code_to_gemoji_names[emoji_code] = ", ".join(
            reverse_unified_reactions_map[emoji_code]
        )

    # Prepare iamcal names map.
    for emoji_dict in EMOJI_DATA:
        emoji_code = get_emoji_code(emoji_dict)
        emoji_code_to_iamcal_names[emoji_code] = ", ".join(emoji_dict["short_names"])

    # Prepare zulip names map.
    for emoji_code in EMOJI_NAME_MAPS:
        canonical_name = EMOJI_NAME_MAPS[emoji_code]["canonical_name"]
        aliases = EMOJI_NAME_MAPS[emoji_code]["aliases"]
        names = [canonical_name]
        names.extend(aliases)
        emoji_code_to_zulip_names[emoji_code] = ", ".join(names)


def get_sorting_info(category: str, sort_order: int) -> str:
    return f"{category} {sort_order}"


def get_images_html(emoji_code: str) -> str:
    images_html = ""
    for emojiset in EMOJISETS:
        images_html += EMOJI_IMAGE_TEMPLATE.format(
            emoji_code=emoji_code,
            emojiset=emojiset,
        )

    return images_html


def generate_emoji_collection() -> None:
    generate_emoji_code_to_emoji_names_maps()
    # Prepare `emoji_collection`.
    for emoji_dict in EMOJI_DATA:
        if not emoji_is_supported(emoji_dict):
            continue
        category = emoji_dict["category"]
        emoji_code = get_emoji_code(emoji_dict)
        sort_order = emoji_dict["sort_order"]
        emoji_collection[category].append(
            {
                "category": category,
                "emoji_code": emoji_code,
                "images_html": get_images_html(emoji_code),
                "gemoji_names": emoji_code_to_gemoji_names.get(emoji_code, ""),
                "iamcal_names": emoji_code_to_iamcal_names.get(emoji_code, ""),
                "zulip_names": emoji_code_to_zulip_names.get(emoji_code, ""),
                "unicode_name": (emoji_dict["name"] or "").lower(),
                "sort_order": sort_order,
                "sorting_info": get_sorting_info(category, sort_order),
            }
        )

    # Sort `emoji_collection`.
    for category in SORTED_CATEGORIES:
        emoji_collection[category].sort(key=lambda x: x["sort_order"])


def main() -> None:
    generate_emoji_collection()

    tbody = ""
    for category in SORTED_CATEGORIES:
        for emoji_entry in emoji_collection[category]:
            tbody += TABLE_ROW_TEMPLATE.format(**emoji_entry)

    with open(OUTPUT_FILE, "w") as fp:
        fp.write(
            EMOJI_LISTING_TEMPLATE.format(
                tbody=tbody,
                table_css=TABLE_CSS,
            )
        )

    print(
        "Done! Open http://localhost:9991/static/generated/emoji/emoji_names_table.html "
        "to view(after starting the dev server)."
    )


if __name__ == "__main__":
    main()
