#!/usr/bin/env python3
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

# pylint: disable=unbalanced-tuple-unpacking

import copy
import os
import re
import sys

from fluent.syntax import parse, serialize
from fluent.syntax.ast import Junk, Message

# clone an existing ftl string as a new key
# eg:
# $ python duplicate-string.py \
#   /source/templates/media-check.ftl window-title \
#   /dest/templates/something.ftl key-name
#
# after running, you'll need to copy the output template file into Anki's source

(src_filename, old_key, dst_filename, new_key) = sys.argv[1:]

# add file as prefix to key
src_prefix = os.path.splitext(os.path.basename(src_filename))[0]
dst_prefix = os.path.splitext(os.path.basename(dst_filename))[0]
old_key = f"{src_prefix}-{old_key}"
new_key = f"{dst_prefix}-{new_key}"


def get_entry(fname, key):
    if not os.path.exists(fname):
        return

    with open(fname, encoding="utf8") as file:
        orig = file.read()
    obj = parse(orig)
    for ent in obj.body:
        if isinstance(ent, Junk):
            raise Exception(f"file had junk! {fname} {ent}")
        elif isinstance(ent, Message):
            if ent.id.name == old_key:
                return copy.deepcopy(ent)


def write_entry(fname, key, entry):
    assert entry
    entry.id.name = key

    if not os.path.exists(fname):
        orig = ""
    else:
        with open(fname, encoding="utf8") as file:
            orig = file.read()
    obj = parse(orig)
    for ent in obj.body:
        if isinstance(ent, Junk):
            raise Exception(f"file had junk! {fname} {ent}")

    obj.body.append(entry)
    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
    with open(fname, "w", encoding="utf8") as file:
        file.write(modified)


# get all existing entries into lang -> entry
entries = {}

i18ndir = os.path.join(os.path.dirname(src_filename), "..")
langs = os.listdir(i18ndir)

for lang in langs:
    if lang == "templates":
        # template
        ftl_path = src_filename
    else:
        # translation
        ftl_path = src_filename.replace("templates", lang)
        ftl_dir = os.path.dirname(ftl_path)

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

    entry = get_entry(ftl_path, old_key)
    if entry:
        entries[lang] = entry
    else:
        assert lang != "templates"

# write them into target files

i18ndir = os.path.join(os.path.dirname(dst_filename), "..")
langs = os.listdir(i18ndir)

for lang in langs:
    if lang == "templates":
        # template
        ftl_path = dst_filename
    else:
        # translation
        ftl_path = dst_filename.replace("templates", lang)
        ftl_dir = os.path.dirname(ftl_path)

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

    if lang in entries:
        entry = entries[lang]
        write_entry(ftl_path, new_key, entry)

print("done")
