#!/usr/bin/env python3

import urllib.request, json, re, time
from functools import cmp_to_key
from locale import strcoll

locales = {
    # Keep in sync with locale.js in zotero-client
    'ar': 'عربي',
    'bg-BG': 'Български',
    'br': 'brezhoneg',
    'ca-AD': 'Català',
    'cs-CZ': 'Čeština',
    'da-DK': 'Dansk',
    'de': 'Deutsch (Deutschland)',
    'en-CA': 'English (Canada)',
    'en-US': 'English',
    'en-GB': 'English (UK)',
    'es-ES': 'Español',
    'et-EE': 'Eesti keel',
    'fa': 'فارسی',
    'fi-FI': 'suomi',
    'fr-FR': 'Français',
    'gl-ES': 'Galego',
    'hu-HU': 'magyar',
    'id-ID': 'Bahasa Indonesia',
    'is-IS': 'íslenska',
    'it-IT': 'Italiano',
    'ja-JP': '日本語',
    'km': 'ខ្មែរ',
    'ko-KR': '한국어',
    'lt-LT': 'Lietuvių',
    'nl-NL': 'Nederlands',
    'nb-NO': 'Norsk bokmål',
    'pl-PL': 'Polski',
    'pt-BR': 'Português (do Brasil)',
    'pt-PT': 'Português (Europeu)',
    'ro-RO': 'Română',
    'ru-RU': 'Русский',
    'sk-SK': 'slovenčina',
    'sl-SI': 'Slovenščina',
    'sr-RS': 'Српски',
    'sv-SE': 'Svenska',
    'ta': 'தமிழ்',
    'th-TH': 'ไทย',
    'tr-TR': 'Türkçe',
    'uk-UA': 'Українська',
    'vi-VN': 'Tiếng Việt',
    'zh-CN': '中文 (简体)',
    'zh-TW': '正體中文 (繁體)',
    
    # Additional dictionaries not included as client locales
    # Names from https://addons.mozilla.org/en-US/firefox/language-tools/
    'de-AT': 'Deutsch (Österreich)',
    'de-CH': 'Deutsch (Schweiz)',
    'el-GR': 'Ελληνικά',
    'es-AR': 'Español (de Argentina)',
    'es-MX': 'Español (de México)',
    'he-HE': 'עברית',
    'hr-HR': 'Hrvatski',
    'lv-LV': 'Latviešu',
}

# Locales to sort before other variants
primary_locales = ['de-DE', 'en-US', 'es-ES']

# Generate list of available dictionaries, sorted by user count descending
dictionaries = []
with urllib.request.urlopen("https://services.addons.mozilla.org/api/v4/addons/language-tools/?app=firefox&type=dictionary") as resp:
    dictionary_info_list = json.loads(resp.read().decode())['results']
    n = 0
    for dictionary_info in dictionary_info_list:
        n += 1
        locale = dictionary_info['target_locale']
        guid = dictionary_info['guid']
        print(str(n) + '/' + str(len(dictionary_info_list)) + ': ' + dictionary_info['target_locale'])
        with urllib.request.urlopen("https://services.addons.mozilla.org/api/v4/addons/search/?guid=" + guid) as resp:
            dictionary = json.loads(resp.read().decode())['results'][0]
            if dictionary['is_disabled'] or dictionary['status'] != 'public':
                print('skipping ' + locale + ' ' + guid)
                continue
            dictionaries.append({
                'id': guid,
                'locale': locale,
                'version': dictionary['current_version']['version'],
                'updated': dictionary['last_updated'],
                'url': dictionary['current_version']['files'][0]['url'],
                'users': dictionary['average_daily_users'],
            })
            time.sleep(1)
    dictionaries.sort(key=lambda x: x.get('users'), reverse=True)

# Find dictionaries best matching the specified locales
final_dictionaries = []
for locale in locales:
    locale_lang = re.split('[-_]', locale)[0]
    # A locale code with the language duplicated (e.g., 'de-DE'), which may not
    # be the actual code
    locale_lang_full = "{}-{}".format(locale_lang, locale_lang.upper())
    
    for i, d in enumerate(dictionaries[:]):
        # Exact match
        if (d['locale'] == locale
                # locale 'de' == dict 'de-DE'
                or (len(locale) == 2 and d['locale'] == locale_lang_full)
                # locale 'bg-BG' -> dict 'bg'
                or (locale == locale_lang_full and d['locale'] == locale_lang)):
            d['name'] = locales[locale]
            final_dictionaries.append(d)
            del(dictionaries[i])
            break
    else:
        # If nothing found, allow missing differing region ('cs-cZ' -> 'cs')
        if len(locale) != 2 and locale != locale_lang_full:
            for i, d in enumerate(dictionaries[:]):
                if d['locale'] == locale_lang:
                    d['name'] = locales[locale]
                    final_dictionaries.append(d)
                    del(dictionaries[i])
                    break

# Sort dictionaries by language code, with a few exceptions
def cmp(a, b):
    for locale in primary_locales:
        if a['locale'] == locale and b['locale'].startswith(locale[0:3]):
            return -1
        if b['locale'] == locale and a['locale'].startswith(locale[0:3]):
            return 1
    return strcoll(a['locale'], b['locale'])

final_dictionaries = sorted(final_dictionaries, key=cmp_to_key(cmp))

print("")

for d in final_dictionaries:
    print("Downloading {}".format(d['url']))
    urllib.request.urlretrieve(
        d['url'],
        'dictionaries/' + d['id'] + '-' + d['version'] + '.xpi'
    )
    del(d['url'])
    time.sleep(1)

with open('dictionaries/dictionaries.json', 'w', encoding='utf-8') as f:
    json.dump(final_dictionaries, f, ensure_ascii=False, sort_keys=True, indent='\t')

# Save a list of unused dictionaries
with open('dictionaries/dictionaries-unused.json', 'w', encoding='utf-8') as f:
    json.dump(dictionaries, f, ensure_ascii=False, indent='\t')

print('\ndone')
