#! /usr/bin/env python3
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import argparse
import xml.etree.ElementTree as ET
import os
import sys
import shutil
import atexit
import subprocess

# Use the project root as the working directory
prevdir = os.getcwd()
workdir = os.path.join(os.path.dirname(__file__), '..', '..')
os.chdir(workdir)
atexit.register(os.chdir, prevdir)

# Include only locales above this threshold (e.g. 70%) in production
l10n_threshold = 0.70

parser = argparse.ArgumentParser()
parser.add_argument(
    '-m', '--macos', default=False, action="store_true", dest="ismacos",
    help='Include the MacOS bundle data')
parser.add_argument(
    '-q', '--qt_path',  default=None, dest="qtpath",
    help='The QT binary path. If not set, we try to guess.')
args = parser.parse_args()

stepnum = 1
def title(text):
    global stepnum
    print(f"\033[96m\033[1mStep {stepnum}\033[0m: \033[97m{text}\033[0m")
    stepnum = stepnum+1

# Step 0
title("Find the Qt localization tools...")
def qtquery(qmake, propname):
    try:
        qtquery = os.popen(f'{qmake} -query {propname}')
        qtpath = qtquery.read().strip()
        if len(qtpath) > 0:
            return qtpath
    finally:
        pass
    return None

qtbinpath = args.qtpath
if qtbinpath is None:
  qtbinpath = qtquery('qmake', 'QT_INSTALL_BINS')
if qtbinpath is None:
    qtbinpath = qtquery('qmake6', 'QT_INSTALL_BINS')
if qtbinpath is None:
    qtbinpath = qtquery('qmake5', 'QT_INSTALL_BINS')
if qtbinpath is None:
    qtbinpath = qtquery('qmake-qt5', 'QT_INSTALL_BINS')
if qtbinpath is None:
    print('Unable to locate qmake tool.')
    sys.exit(1)

if not os.path.isdir(qtbinpath):
    print(f"QT path is not a diretory: {qtbinpath}")
    sys.exit(1)

lupdate = os.path.join(qtbinpath, 'lupdate')
lconvert = os.path.join(qtbinpath, 'lconvert')
lrelease = os.path.join(qtbinpath, 'lrelease')

# Step 0
# Let's update the i18n repo
os.system(f"git submodule init")
os.system(f"git submodule update --remote --depth 1 i18n")

# Step 1
# Go through the i18n repo, check each XLIFF file and take
# note which locale is complete above the minimum threshold.
# Adds path of .xliff and .ts to l10n_files.
title("Validate the XLIFF file...")
l10n_files = []
for locale in os.listdir('i18n'):
    # Skip non folders
    if not os.path.isdir(os.path.join('i18n', locale)):
        continue

    # Skip hidden folders
    if locale.startswith('.'):
        continue

    xliff_path = os.path.join('i18n', locale, 'mozillavpn.xliff')

    # If it's the source locale (en), ignore parsing for completeness and
    # add it to the list.
    if locale == 'en':
        print(f'OK\t- en added (reference locale)')
        l10n_files.append({
            'locale': 'en',
            'ts': os.path.join('translations', 'generated', 'mozillavpn_en.ts'),
            'xliff': xliff_path
        })
        continue

    tree = ET.parse(xliff_path)
    root = tree.getroot()

    sources = 0
    translations = 0

    for element in root.iter('{urn:oasis:names:tc:xliff:document:1.2}source'):
        sources += 1
    for element in root.iter('{urn:oasis:names:tc:xliff:document:1.2}target'):
        translations += 1

    completeness = translations/(sources*1.0)

    # Ignore locale with less than 70% of completeness
    if completeness < l10n_threshold:
        print(f'KO\t- {locale} is translated at {round(completeness*100, 2)}%, at least {l10n_threshold*100}% is needed')
        continue  # Not enough translations next file please

    print(f'OK\t- {locale} added ({round(completeness*100, 2)}% translated)')
    l10n_files.append({
        'locale': locale,
        'ts': os.path.join('translations', 'generated', f'mozillavpn_{locale}.ts'),
        'xliff': xliff_path
    })

# Step 2
title("Create folders and localization files for the languages...")
for file in l10n_files:
    locdirectory = os.path.join('translations', 'generated', file['locale'])
    os.makedirs(locdirectory, exist_ok=True)
    locversion = os.path.join(locdirectory, f'locversion.plist')
    with open(locversion, 'w') as locversion_file:
        locversion_file.write(f"""<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"
\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<dict>
    <key>LprojCompatibleVersion</key>
    <string>123</string>
    <key>LprojLocale</key>
    <string>{file['locale']}</string>
    <key>LprojRevisionLevel</key>
    <string>1</string>
    <key>LprojVersion</key>
    <string>123</string>
</dict>
</plist>""")

with open(os.path.join('translations', 'generated', 'macos.pri'), 'w') as macospri:
    macospri.write('### AUTOGENERATED! DO NOT EDIT!! ###\n')
    for file in l10n_files:
        macospri.write(f"LANGUAGES_FILES_{file['locale']}.files += $$PWD/{file['locale']}/locversion.plist\n")
        macospri.write(f"LANGUAGES_FILES_{file['locale']}.path = Contents/Resources/{file['locale']}.lproj\n")
        macospri.write(f"QMAKE_BUNDLE_DATA += LANGUAGES_FILES_{file['locale']}\n\n")

# Step 3
title("Write resource file to import the locales that are ready...")
with open('translations/generated/translations.qrc', 'w') as qrcfile:
    qrcfile.write('<!-- AUTOGENERATED! DO NOT EDIT!! -->\n')
    qrcfile.write('<RCC>\n')
    qrcfile.write('    <qresource prefix="/i18n">\n')
    for file in l10n_files:
        qrcfile.write(f'        <file>mozillavpn_{file["locale"]}.qm</file>\n')
    qrcfile.write('    </qresource>\n')
    qrcfile.write('</RCC>\n')

# Step 4
title("Generate the Js/C++ string definitions...")
try:
    subprocess.call([sys.executable, os.path.join('scripts', 'utils', 'generate_strings.py'),
                     '-o', os.path.join('translations', 'generated'),
                     os.path.join('translations', 'strings.yaml')])
except Exception as e:
    print("generate_strings.py failed. Try with:\n\tpip3 install -r requirements.txt --user")
    print(e)
    exit(1)

# Build a dummy project to glob together everything that might contain strings.
title("Scanning for new strings...")
def scan_sources(projfile, dirpath):
    projfile.write(f"HEADERS += $$files({dirpath}/*.h, true)\n")
    projfile.write(f"SOURCES += $$files({dirpath}/*.cpp, true)\n")
    projfile.write(f"RESOURCES += $$files({dirpath}/*.qrc, true)\n\n")

with open('translations/generated/dummy.pro', 'w') as dummyproj:
    dummyproj.write('### AUTOGENERATED! DO NOT EDIT!! ###\n')
    dummyproj.write(f"HEADERS += l18nstrings.h\n")
    dummyproj.write(f"SOURCES += l18nstrings_p.cpp\n")
    dummyproj.write(f"SOURCES += ../l18nstrings.cpp\n\n")
    for l10n_file in l10n_files:
        dummyproj.write(f"TRANSLATIONS += {os.path.basename(l10n_file['ts'])}\n")

    dummyproj.write("\n")
    scan_sources(dummyproj, '../../src')
    scan_sources(dummyproj, '../../nebula')

# Step 5
title("Generate translation resources...")
for l10n_file in l10n_files:
    os.system(f"{lconvert} -if xlf -i {l10n_file['xliff']} -o {l10n_file['ts']}")
os.system(f"{lupdate} translations/generated/dummy.pro")
for l10n_file in l10n_files:
    os.system(f"{lrelease} -idbased {l10n_file['ts']}")

print(f'Imported {len(l10n_files)} locales')

git = os.popen(f'git submodule status i18n')
git_commit_hash = git.read().strip().replace("+","").split(' ')[0]
print(f'Current commit:  https://github.com/mozilla-l10n/mozilla-vpn-client-l10n/commit/{git_commit_hash}')

[((401, 412), 'os.getcwd', 'os.getcwd', ([], {}), '()\n', (410, 412), False, 'import os\n'), ((475, 492), 'os.chdir', 'os.chdir', (['workdir'], {}), '(workdir)\n', (483, 492), False, 'import os\n'), ((493, 527), 'atexit.register', 'atexit.register', (['os.chdir', 'prevdir'], {}), '(os.chdir, prevdir)\n', (508, 527), False, 'import atexit\n'), ((630, 655), 'argparse.ArgumentParser', 'argparse.ArgumentParser', ([], {}), '()\n', (653, 655), False, 'import argparse\n'), ((1905, 1939), 'os.path.join', 'os.path.join', (['qtbinpath', '"""lupdate"""'], {}), "(qtbinpath, 'lupdate')\n", (1917, 1939), False, 'import os\n'), ((1951, 1986), 'os.path.join', 'os.path.join', (['qtbinpath', '"""lconvert"""'], {}), "(qtbinpath, 'lconvert')\n", (1963, 1986), False, 'import os\n'), ((1998, 2033), 'os.path.join', 'os.path.join', (['qtbinpath', '"""lrelease"""'], {}), "(qtbinpath, 'lrelease')\n", (2010, 2033), False, 'import os\n'), ((2073, 2105), 'os.system', 'os.system', (['f"""git submodule init"""'], {}), "(f'git submodule init')\n", (2082, 2105), False, 'import os\n'), ((2106, 2164), 'os.system', 'os.system', (['f"""git submodule update --remote --depth 1 i18n"""'], {}), "(f'git submodule update --remote --depth 1 i18n')\n", (2115, 2164), False, 'import os\n'), ((2406, 2424), 'os.listdir', 'os.listdir', (['"""i18n"""'], {}), "('i18n')\n", (2416, 2424), False, 'import os\n'), ((7168, 7224), 'os.system', 'os.system', (['f"""{lupdate} translations/generated/dummy.pro"""'], {}), "(f'{lupdate} translations/generated/dummy.pro')\n", (7177, 7224), False, 'import os\n'), ((7363, 7401), 'os.popen', 'os.popen', (['f"""git submodule status i18n"""'], {}), "(f'git submodule status i18n')\n", (7371, 7401), False, 'import os\n'), ((436, 461), 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), '(__file__)\n', (451, 461), False, 'import os\n'), ((1779, 1790), 'sys.exit', 'sys.exit', (['(1)'], {}), '(1)\n', (1787, 1790), False, 'import sys\n'), ((1799, 1823), 'os.path.isdir', 'os.path.isdir', (['qtbinpath'], {}), '(qtbinpath)\n', (1812, 1823), False, 'import os\n'), ((1882, 1893), 'sys.exit', 'sys.exit', (['(1)'], {}), '(1)\n', (1890, 1893), False, 'import sys\n'), ((2615, 2663), 'os.path.join', 'os.path.join', (['"""i18n"""', 'locale', '"""mozillavpn.xliff"""'], {}), "('i18n', locale, 'mozillavpn.xliff')\n", (2627, 2663), False, 'import os\n'), ((3049, 3069), 'xml.etree.ElementTree.parse', 'ET.parse', (['xliff_path'], {}), '(xliff_path)\n', (3057, 3069), True, 'import xml.etree.ElementTree as ET\n'), ((4033, 4090), 'os.path.join', 'os.path.join', (['"""translations"""', '"""generated"""', "file['locale']"], {}), "('translations', 'generated', file['locale'])\n", (4045, 4090), False, 'import os\n'), ((4095, 4135), 'os.makedirs', 'os.makedirs', (['locdirectory'], {'exist_ok': '(True)'}), '(locdirectory, exist_ok=True)\n', (4106, 4135), False, 'import os\n'), ((4153, 4200), 'os.path.join', 'os.path.join', (['locdirectory', 'f"""locversion.plist"""'], {}), "(locdirectory, f'locversion.plist')\n", (4165, 4200), False, 'import os\n'), ((7090, 7167), 'os.system', 'os.system', (['f"""{lconvert} -if xlf -i {l10n_file[\'xliff\']} -o {l10n_file[\'ts\']}"""'], {}), '(f"{lconvert} -if xlf -i {l10n_file[\'xliff\']} -o {l10n_file[\'ts\']}")\n', (7099, 7167), False, 'import os\n'), ((7258, 7309), 'os.system', 'os.system', (['f"""{lrelease} -idbased {l10n_file[\'ts\']}"""'], {}), '(f"{lrelease} -idbased {l10n_file[\'ts\']}")\n', (7267, 7309), False, 'import os\n'), ((1211, 1249), 'os.popen', 'os.popen', (['f"""{qmake} -query {propname}"""'], {}), "(f'{qmake} -query {propname}')\n", (1219, 1249), False, 'import os\n'), ((4746, 4800), 'os.path.join', 'os.path.join', (['"""translations"""', '"""generated"""', '"""macos.pri"""'], {}), "('translations', 'generated', 'macos.pri')\n", (4758, 4800), False, 'import os\n'), ((2474, 2502), 'os.path.join', 'os.path.join', (['"""i18n"""', 'locale'], {}), "('i18n', locale)\n", (2486, 2502), False, 'import os\n'), ((3807, 3875), 'os.path.join', 'os.path.join', (['"""translations"""', '"""generated"""', 'f"""mozillavpn_{locale}.ts"""'], {}), "('translations', 'generated', f'mozillavpn_{locale}.ts')\n", (3819, 3875), False, 'import os\n'), ((5790, 5845), 'os.path.join', 'os.path.join', (['"""scripts"""', '"""utils"""', '"""generate_strings.py"""'], {}), "('scripts', 'utils', 'generate_strings.py')\n", (5802, 5845), False, 'import os\n'), ((5874, 5915), 'os.path.join', 'os.path.join', (['"""translations"""', '"""generated"""'], {}), "('translations', 'generated')\n", (5886, 5915), False, 'import os\n'), ((5938, 5982), 'os.path.join', 'os.path.join', (['"""translations"""', '"""strings.yaml"""'], {}), "('translations', 'strings.yaml')\n", (5950, 5982), False, 'import os\n'), ((2914, 2975), 'os.path.join', 'os.path.join', (['"""translations"""', '"""generated"""', '"""mozillavpn_en.ts"""'], {}), "('translations', 'generated', 'mozillavpn_en.ts')\n", (2926, 2975), False, 'import os\n'), ((6853, 6886), 'os.path.basename', 'os.path.basename', (["l10n_file['ts']"], {}), "(l10n_file['ts'])\n", (6869, 6886), False, 'import os\n')]