# manim_fa/translit.py
# -*- coding: utf-8 -*-
"""
توابع ترانسلیت (Latin -> Persian) برای پلاگین manim_fa.

تابع اصلی:
    translit_to_fa(text: str, convert_numbers: bool = True) -> str

توضیحات:
- این پیاده‌سازی یک تبدیل قاعده‌مبنا و کاربردی است که برای ورودی‌های رایج
  (مثل "salam", "khodaa", "shab", "mashin") خروجی فارسی معقول تولید می‌کند.
- تبدیل کامل آوایی فارسی نیازمند قواعد جامع‌تر (تحلیل هجا، موقعیت مصوت‌ها و غیره)
  است و در این پیاده‌سازی کامل پیاده نشده — اما برای موارد کاربردی و نمونه مناسب است.
- گزینه `convert_numbers=True` ارقام لاتین را به ارقام فارسی تبدیل می‌کند.
- تابع حروف بزرگ/کوچک را نادیده می‌گیرد و نگه‌داری فاصله‌ها و علائم نگارشی را حفظ می‌کند.

نکات و محدودیت‌ها:
- این تابع مکانیسم پیچیدهٔ تشخیص مصوت‌های کوتاه (َُِ) را ندارد و
  مصوت‌های کوتاه را با معادل‌های ساده (حروف الف، ی، و) جایگزین می‌کند؛
  بنابراین گاهی باید خروجی دستی کمی ویرایش شود.
- اگر نیاز به ترانسلیت دقیق‌تر داری (قواعد آوایی، نشانه‌گذاری دقیق مصوت‌ها)،
  پیشنهاد می‌کنم از یک کتابخانهٔ زبانی یا یک مدل مخصوص استفاده کنی و این
  تابع را به عنوان fallback نگه داری کنی.
"""

import re

# ترتیب مهم است: ابتدا digraphs (دوحرفی‌ها) را تعریف می‌کنیم تا با جایگزینی
# درست، از تداخل با جایگذاری تک‌حرفی جلوگیری شود.
_DIGRAPH_MAP = {
    # دوحرفی‌های رایج
    "kh": "خ",
    "gh": "غ",
    "ch": "چ",
    "sh": "ش",
    "zh": "ژ",  # برای برخی کاربران 'zh' را برای ژ استفاده می‌کنند
    "ph": "ف",  # در برخی ترانسلیت‌ها ph -> ف
    "th": "ث",  # در برخی موارد
    # حالت‌های با نماد لاتین (با ^ یا ')
    "aa": "آ",  # aa یا â -> آ
    "â": "آ",
    "ou": "او",
    "ow": "او",
    "oo": "و",
    "ee": "ی",
}

# مپ تک‌حرفی — معادل تقریبی
_SINGLE_MAP = {
    "a": "ا",
    "b": "ب",
    "p": "پ",
    "t": "ت",
    "s": "س",
    "j": "ج",
    "c": "ک",  # c -> ک (گاهی س، اما در قالب ساده ک بهتر است)
    "k": "ک",
    "g": "گ",
    "q": "ق",
    "f": "ف",
    "v": "و",
    "w": "و",
    "h": "ه",
    "x": "خ",  # x -> خ در برخی نگارش‌ها
    "y": "ی",
    "i": "ی",
    "o": "و",
    "u": "و",
    "e": "ِ",  # e به صورت نیم‌مصوت کوچک؛ در خروجی ما معمولاً نگهداری نمی‌شود
    "r": "ر",
    "l": "ل",
    "m": "م",
    "n": "ن",
    "z": "ز",
    "d": "د",
    "'": "ء",  # آدم‌ها گاهی ' را برای همزه می‌گذارند
    # اعداد و علائم در این بخش نیامده‌اند؛ اعداد به صورت جداگانه تبدیل می‌شوند
}

# ارقام لاتین -> ارقام فارسی
_NUM_MAP = str.maketrans("0123456789", "۰۱۲۳۴۵۶۷۸۹")


def _replace_digraphs(text: str) -> str:
    """
    جایگزینی جفت‌حروف مشخص (digraphs) در متن با حروف فارسی متناظر.
    جایگزینی به صورت case-insensitive انجام می‌شود.
    """
    # برای اطمینان از اینکه جایگزینی تکراری درست کار کند، از regex با تابع استفاده می‌کنیم.
    # مرتب‌سازی کلیدها بر اساس طول نزولی تا ابتدا digraph های طولانی‌تر بررسی شوند.
    keys = sorted(_DIGRAPH_MAP.keys(), key=len, reverse=True)
    pattern = re.compile("|".join(re.escape(k) for k in keys), flags=re.IGNORECASE)

    def _repl(match):
        token = match.group(0).lower()
        return _DIGRAPH_MAP.get(token, token)

    return pattern.sub(_repl, text)


def _replace_single_letters(text: str) -> str:
    """
    جایگزینی تک‌حرفی‌ها. این تابع متن را به حروف تبدیل می‌کند.
    برای کارآیی، همه حروف غیرالفبایی (غیر a-z) را حفظ می‌کند.
    """
    result_chars = []
    for ch in text:
        lower = ch.lower()
        if lower in _SINGLE_MAP:
            result_chars.append(_SINGLE_MAP[lower])
        else:
            # اگر کاراکتر لاتین نیست (مثلاً فاصله، نقطه، یا حرف فارسی فعلاً)، آن را بدون تغییر می‌گذاریم
            result_chars.append(ch)
    return "".join(result_chars)


def _post_process_cleanup(text: str) -> str:
    """
    پاکسازی‌های نهایی:
    - حذف یا اصلاح مواردی که ممکن است نتیجهٔ ناخوشایند تولید کنند
    - تبدیل چند الف متوالی به تنها یک آ در موارد مناسب
    - تبدیل نماد نیم‌مصوت 'ِ' (e) به حذف یا به ی مناسب در برخی موقعیت‌ها
    """
    # حذف فاصله‌های متعدد
    text = re.sub(r"\s+", " ", text)

    # تبدیل توالی 'آا' یا 'اآ' به 'آ' (در برخی تبدیل‌ها ممکن است افزونگی ایجاد شود)
    text = re.sub(r"آا+", "آ", text)
    text = re.sub(r"اآ+", "آ", text)

    # تبدیل توالی 'اا' به 'ا' مگر در موارد خیلی خاص
    text = re.sub(r"ا{2,}", "ا", text)

    # تبدیل نماد 'ِ' (موقتی از mapping e) به حذف (چون فارسی معمولا مصوت کوتاه را نمی‌نویسد)
    # اگر بخواهی می‌توانیم آن را تبدیل به 'ِ' نگهداریم، ولی در حالت پیش‌فرض حذف می‌کنیم.
    text = text.replace("ِ", "")

    # حذف همزهٔ تکراری
    text = re.sub(r"ء{2,}", "ء", text)

    # حذف فاصلهٔ قبل از علائم نگارشی
    text = re.sub(r"\s+([،؛\.\,\!\?])", r"\1", text)

    return text.strip()


def translit_to_fa(text: str, convert_numbers: bool = True) -> str:
    """
    تبدیل متن لاتین به تقریباً متن فارسی.

    پارامترها:
    - text: رشته ورودی حاوی حروف لاتین (می‌تواند شامل فاصله و علائم نگارشی باشد)
    - convert_numbers: اگر True باشد، ارقام 0-9 به ارقام فارسی تبدیل می‌شوند

    بازگشتی:
    - رشتهٔ متنی به حروف فارسی (تقریبی)

    مثال‌ها:
    >>> translit_to_fa("salam")
    'سلام'
    >>> translit_to_fa("khodaa khodaa")
    'خدا خدا'   # توجه: 'khodaa' -> 'خدا' در بسیاری از موارد نتیجهٔ مناسب خواهد بود
    """
    if not isinstance(text, str):
        return text

    # قدم 1: اگر کاربر خواست، ارقام را تبدیل کن
    if convert_numbers:
        text = text.translate(_NUM_MAP)

    # قدم 2: حفظ علائم نگارشی و فاصل‌ها؛ اما برای جایگزینی کارآمدتر، ابتدا digraphs را تعویض می‌کنیم
    # کار را با یک پیش‌پردازش ساده جهت جلوگیری از تغییر حروف فارسی موجود آغاز می‌کنیم:
    # اگر متن حاوی کاراکترهای فارسی است، فرض می‌کنیم بخش فارسی را نگه داریم.
    # بنابراین تنها روی حروف لاتین و علائم مرتبط عمل می‌کنیم.
    # برای ساده‌سازی، ابتدا متن را جدا به توکن‌هایی تقسیم می‌کنیم: بلوک‌های لاتین و غیرلاتین.
    tokens = re.findall(r"[A-Za-z\u0027\u00E2]+|[^A-Za-z\u0027\u00E2]+", text)

    out_tokens = []
    for tok in tokens:
        # اگر توکن شامل حداقل یک حرف لاتین است، ترانسلیت را اعمال کن
        if re.search(r"[A-Za-z]", tok):
            # ۱) جایگزینی digraphs
            t = _replace_digraphs(tok)
            # ۲) جایگزینی حروف تک
            t = _replace_single_letters(t)
            out_tokens.append(t)
        else:
            # غیرلاتین (فاصله، علائم، یا ممکن است فارسی از قبل) را بدون تغییر اضافه کن
            out_tokens.append(tok)

    out = "".join(out_tokens)
    # قدم آخر: پاک‌سازی موارد اضافی
    out = _post_process_cleanup(out)
    return out


# برای تست سریع هنگام اجرای مستقیم فایل
if __name__ == "__main__":
    examples = [
        "salam",
        "salam alaykom",
        "khodaa",
        "khodaa khodaa",
        "shab",
        "mashin",
        "tehran",
        "khoob",
        "ghazal",
        "ziba",
        "eshgh",
        "man",
        "to",
        "khane",
        "ostad",
        "yaar",
        "shoma",
        "philosophy",
        "123 test",
    ]
    for ex in examples:
        print(f"{ex!r} -> {translit_to_fa(ex)}")

# تابع فنگلش به فارسی
