import os
import argostranslate.package
import argostranslate.translate
from tkinter import filedialog, Tk
import pdfplumber
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from PyPDF2 import PdfReader, PdfWriter
from io import BytesIO
from tqdm import tqdm
import re
import sys
import traceback

# Limbile disponibile
SOURCE_LANGUAGES = {
    "1": ("en", "Engleză"),
    "2": ("fr", "Franceză"),
    "3": ("ru", "Rusă"),
    "4": ("el", "Greacă"),
    "5": ("grc", "Greacă veche"),
    "6": ("es", "Spaniolă"),
    "7": ("de", "Germană"),
    "8": ("it", "Italiană"),
    "9": ("la", "Latină")
}

TARGET_LANGUAGES = {
    "1": ("ro", "Română"),
    "2": ("en", "Engleză"),
    "3": ("fr", "Franceză")
}

# Configurare traducere Argos
def setup_argos_translation(from_lang, to_lang):
    try:
        print(f"Se configurează traducerea {from_lang} -> {to_lang}...")
        argostranslate.package.update_package_index()
        available_packages = argostranslate.package.get_available_packages()
        
        package = next((p for p in available_packages if p.from_code == from_lang and p.to_code == to_lang), None)
        if package:
            if package not in argostranslate.package.get_installed_packages():
                package_path = package.download()
                argostranslate.package.install_from_path(package_path)
            return True
        
        if from_lang != "en" and to_lang != "en":
            package1 = next((p for p in available_packages if p.from_code == from_lang and p.to_code == "en"), None)
            package2 = next((p for p in available_packages if p.from_code == "en" and p.to_code == to_lang), None)
            if package1 and package2:
                for pkg in [package1, package2]:
                    if pkg not in argostranslate.package.get_installed_packages():
                        package_path = pkg.download()
                        argostranslate.package.install_from_path(package_path)
                return True
        return False
    except Exception as e:
        print(f"Eroare la configurarea traducătorului: {str(e)}")
        return False

# Selectare limbă
def select_language(prompt, languages):
    print(prompt)
    for num, (_, name) in languages.items():
        print(f"{num}: {name}")
    choice = input("Introdu numărul limbii: ").strip()
    return languages.get(choice, (None, None))[0]

# Extragere text și proprietăți
def extract_text_with_properties(pdf_file):
    text_lines = []
    try:
        with pdfplumber.open(pdf_file) as pdf:
            for page_num, page in enumerate(pdf.pages, 1):
                words = page.extract_words(keep_blank_chars=True)
                for word in words:
                    text_lines.append({
                        "text": word["text"],
                        "x0": word["x0"],
                        "top": word["top"],
                        "x1": word["x1"],
                        "bottom": word["bottom"],
                        "page": page_num,
                        "width": page.width,
                        "height": page.height,
                        "fontname": word.get("fontname", "DejaVuSans"),
                        "size": word.get("size", 12)
                    })
        return text_lines
    except Exception as e:
        print(f"Eroare la extragerea textului: {str(e)}")
        return None

# Gestionare formule matematice
def handle_math_formulas(text):
    math_pattern = r'\$\$?.*?\$\$?|\$.*?\$'
    formulas = re.findall(math_pattern, text)
    text_with_placeholder = re.sub(math_pattern, "###MATH###", text)
    return formulas, text_with_placeholder

# Traducere text
def translate_with_formulas(text, from_lang, to_lang):
    try:
        formulas, text_placeholder = handle_math_formulas(text)
        translated = argostranslate.translate.translate(text_placeholder, from_lang, to_lang)
        for formula in formulas:
            translated = translated.replace("###MATH###", formula, 1)
        return translated
    except Exception as e:
        print(f"Eroare la traducere: {str(e)}")
        return text

# Calcul lățime text
def get_text_width(text, fontname, fontsize):
    try:
        font = pdfmetrics.getFont(fontname)
        return font.stringWidth(text, fontsize)
    except:
        return pdfmetrics.stringWidth(text, fontname, fontsize)

# Generare PDF tradus
def generate_translated_pdf(text_data, translated_texts, input_pdf, output_file):
    try:
        pdfmetrics.registerFont(TTFont("DejaVuSans", "DejaVuSans.ttf"))
        pdfmetrics.registerFont(TTFont("DejaVuSans-Bold", "DejaVuSans-Bold.ttf"))
        pdfmetrics.registerFont(TTFont("DejaVuSans-Oblique", "DejaVuSans-Oblique.ttf"))

        pdf_reader = PdfReader(input_pdf)
        pdf_writer = PdfWriter()
        temp_pdf = BytesIO()
        pdf_canvas = canvas.Canvas(temp_pdf, pagesize=letter)

        current_page = 1
        for i, item in enumerate(text_data):
            if item["page"] != current_page:
                pdf_canvas.showPage()
                current_page = item["page"]
                pdf_canvas.setPageSize((item["width"], item["height"]))

            translated_text = translated_texts[i]
            x0 = item["x0"]
            y_pos = item["height"] - item["bottom"]

            fontname = "DejaVuSans"
            if "Bold" in item["fontname"]:
                fontname = "DejaVuSans-Bold"
            elif "Italic" in item["fontname"] or "Oblique" in item["fontname"]:
                fontname = "DejaVuSans-Oblique"

            font_size = item["size"]
            original_width = item["x1"] - item["x0"]
            text_width = get_text_width(translated_text, fontname, font_size)

            if text_width > original_width:
                font_size = font_size * (original_width / text_width)
                font_size = max(font_size, 6)

            pdf_canvas.setFont(fontname, font_size)
            pdf_canvas.drawString(x0, y_pos, translated_text)

        pdf_canvas.save()
        temp_pdf.seek(0)

        translated_pdf = PdfReader(temp_pdf)
        for page_num in range(len(pdf_reader.pages)):
            original_page = pdf_reader.pages[page_num]
            translated_page = translated_pdf.pages[page_num] if page_num < len(translated_pdf.pages) else None
            new_page = original_page
            if translated_page:
                new_page.merge_page(translated_page)
            pdf_writer.add_page(new_page)

        with open(output_file, "wb") as f:
            pdf_writer.write(f)
        print(f"PDF generat: {output_file}")
    except Exception as e:
        print(f"Eroare la generarea PDF-ului: {str(e)}")

# Funcția principală
def process_pdf_translation():
    try:
        from_lang = select_language("Selectați limba sursă:", SOURCE_LANGUAGES)
        if not from_lang:
            return

        to_lang = select_language("Selectați limba țintă:", TARGET_LANGUAGES)
        if not to_lang:
            return

        if not setup_argos_translation(from_lang, to_lang):
            print("Eroare la configurarea traducătorului.")
            return

        root = Tk()
        root.withdraw()
        pdf_file = filedialog.askopenfilename(title="Selectează PDF", filetypes=[("PDF files", "*.pdf")])
        root.destroy()

        if not pdf_file:
            return

        output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "translated")
        os.makedirs(output_dir, exist_ok=True)

        text_data = extract_text_with_properties(pdf_file)
        if not text_data:
            return

        translated_texts = [translate_with_formulas(item["text"], from_lang, to_lang) for item in text_data]
        output_file = os.path.join(output_dir, f"{os.path.splitext(os.path.basename(pdf_file))[0]}_translated_{to_lang}.pdf")
        generate_translated_pdf(text_data, translated_texts, pdf_file, output_file)

    except Exception as e:
        print(f"Eroare: {str(e)}")

if __name__ == "__main__":
    process_pdf_translation()