#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import os
import json
import re
import sys
import polib
import shutil
from fluent.syntax import parse, serialize
from fluent.syntax.ast import Message, TextElement, Identifier, Pattern, Junk

# extract a translated string from strings.json and insert it into ftl
# eg:
# $ python extract-po-string.py strings.json /path/to/templates/media-check.ftl delete-unused "Delete Unused Media" ""
# $ python extract-po-string.py strings.json /path/to/templates/media-check.ftl delete-unused "%(a)s %(b)s" "%(a)s=$val1,%(b)s=$val2"

json_filename, ftl_filename, key, msgid_substring, repls = sys.argv[1:]

# split up replacements
replacements = []
for repl in repls.split(","):
    if not repl:
        continue
    replacements.append(repl.split("="))

# add file as prefix to key
prefix = os.path.splitext(os.path.basename(ftl_filename))[0]
key = f"{prefix}-{key}"

strings = json.load(open(json_filename, "r"))

msgids = []
if msgid_substring in strings["en"]:
    # is the ID an exact match?
    msgids.append(msgid_substring)
else:
    for id in strings["en"].keys():
        if msgid_substring in id:
            msgids.append(id)

msgid = None
if len(msgids) == 0:
    print("no IDs matched")
    sys.exit(1)
elif len(msgids) == 1:
    msgid = msgids[0]
else:
    for c, id in enumerate(msgids):
        print(f"* {c}: {id}")
    msgid = msgids[int(input("number to use? "))]


def transform_entry(entry):
    if isinstance(entry, str):
        return transform_string(entry)
    else:
        return [transform_string(e) for e in entry]


def transform_string(msg):
    for (old, new) in replacements:
        msg = msg.replace(old, f"{new}")
    # strip leading/trailing whitespace
    return msg.strip()


to_insert = []
for lang in strings.keys():
    entry = strings[lang].get(msgid)
    if not entry:
        continue
    entry = transform_entry(entry)
    if entry:
        print(f"{lang} had translation {entry}")
        to_insert.append((lang, entry))

plurals = json.load(open("plurals.json"))


def plural_text(key, lang, translation):
    lang = re.sub("(_|-).*", "", lang)

    # extract the variable - there should be only one
    var = re.findall(r"{(\$.*?)}", translation[0])
    if not len(var) == 1:
        return None
    var = var[0]

    buf = f"{key} = {{ {var} ->\n"

    # for each of the plural forms except the last
    for idx, msg in enumerate(translation[:-1]):
        plural_form = plurals[lang][idx]
        buf += f"    [{plural_form}] {msg}\n"

    # add the catchall
    msg = translation[-1]
    buf += f"   *[other] {msg}\n"
    buf += "  }\n"
    return buf


# add a non-pluralized message. works via fluent.syntax, so can automatically
# indent, etc
def add_simple_message(fname, key, message):
    orig = ""
    if os.path.exists(fname):
        orig = open(fname).read()

    obj = parse(orig)
    for ent in obj.body:
        if isinstance(ent, Junk):
            raise Exception(f"file had junk! {fname} {ent}")
    obj.body.append(Message(Identifier(key), Pattern([TextElement(message)])))

    modified = serialize(obj, with_junk=True)
    # escape leading dots
    modified = re.sub(r"(?ms)^( +)\.", '\\1{"."}', modified)

    # ensure the resulting serialized file is valid by parsing again
    obj = parse(modified)
    for ent in obj.body:
        if isinstance(ent, Junk):
            raise Exception(f"introduced junk! {fname} {ent}")

    # it's ok, write it out
    open(fname, "w").write(modified)


def add_message(fname, key, translation):
    # simple, non-plural form?
    if isinstance(translation, str):
        add_simple_message(fname, key, translation)
    else:
        raise
        return plural_text(key, lang, translation)


print()
input("proceed? ctrl+c to abort")

i18ndir = os.path.join(os.path.dirname(ftl_filename), "..")

# for each language's translation
for lang, translation in to_insert:
    if lang == "en":
        # template
        ftl_path = ftl_filename
    else:
        # translation
        ftl_path = ftl_filename.replace("templates", lang)
        ftl_dir = os.path.dirname(ftl_path)

        if not os.path.exists(ftl_dir):
            os.mkdir(ftl_dir)

    add_message(ftl_path, key, translation)

# copy file from repo into src
srcdir = os.path.join(i18ndir, "..", "..")
src_filename = os.path.join(srcdir, os.path.basename(ftl_filename))
shutil.copy(ftl_filename, src_filename)

print("done")
