#!/usr/bin/env python3
"""
gftools lang

Adds sample text for a given language using the specified UDHR translation.

Usage:

# Standard usage. Output lang metadata to a dir. Does not overwrite existing data.
gftools lang-sample-text -l ./languages/en.textproto ./udhr_translations/en.xml

"""

from absl import app
from absl import flags
from gflanguages import LoadLanguages, LoadRegions
from gftools import fonts_public_pb2
from gftools.util.udhr import Udhr
from google.protobuf import text_format
from lxml import etree
import csv
import glob
import os
import re
import yaml

FLAGS = flags.FLAGS
flags.DEFINE_string("lang", None, "Path to lang metadata package", short_name="l")
flags.DEFINE_string("udhrs", None, "Path to UDHR translations (XML)", short_name="u")
flags.DEFINE_string(
    "samples",
    None,
    "Path to per-family samples from noto-data-dev repo",
    short_name="s",
)


def _ReadProto(proto, path):
    with open(path, "r", encoding="utf-8") as f:
        proto = text_format.Parse(f.read(), proto)
        return proto


def _WriteProto(proto, path, comments=None):
    with open(path, "w", newline="") as f:
        textproto = text_format.MessageToString(proto, as_utf8=True)
        if comments is not None:
            lines = [
                s if s not in comments else s + "  # " + comments[s]
                for s in textproto.split("\n")
            ]
            textproto = "\n".join(lines)
        f.write(textproto)


def _GetLanguageForUdhr(languages, udhr):
    for l in languages.values():
        if (
            l.language == udhr.iso639_3 and l.script == udhr.iso15924
        ) or l.id == udhr.bcp47:
            return l

    language = fonts_public_pb2.LanguageProto()
    language.id = udhr.bcp47
    language.language = udhr.bcp47.split("_")[0]
    language.script = udhr.iso15924
    language.name = udhr.name.replace(" (", ", ").replace(")", "")
    return language


def _ReplaceInSampleText(languages):
    for l in languages.values():
        if l.script == "Latn" or not l.HasField("sample_text"):
            continue
        if "-" in l.sample_text.masthead_full:
            l.sample_text.masthead_full = (
                l.sample_text.masthead_full.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.masthead_partial:
            l.sample_text.masthead_partial = (
                l.sample_text.masthead_partial.replace(" - ", " ")
                .replace("-", "")
                .strip()
            )
        if "-" in l.sample_text.styles:
            l.sample_text.styles = (
                l.sample_text.styles.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.tester:
            l.sample_text.tester = (
                l.sample_text.tester.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.poster_sm:
            l.sample_text.poster_sm = (
                l.sample_text.poster_sm.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.poster_md:
            l.sample_text.poster_md = (
                l.sample_text.poster_md.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.poster_lg:
            l.sample_text.poster_lg = (
                l.sample_text.poster_lg.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.specimen_48:
            l.sample_text.specimen_48 = (
                l.sample_text.specimen_48.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.specimen_36:
            l.sample_text.specimen_36 = (
                l.sample_text.specimen_36.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.specimen_32:
            l.sample_text.specimen_32 = (
                l.sample_text.specimen_32.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.specimen_21:
            l.sample_text.specimen_21 = (
                l.sample_text.specimen_21.replace(" - ", " ").replace("-", "").strip()
            )
        if "-" in l.sample_text.specimen_16:
            l.sample_text.specimen_16 = (
                l.sample_text.specimen_16.replace(" - ", " ").replace("-", "").strip()
            )

        _WriteProto(l, os.path.join(FLAGS.lang, "languages", l.id + ".textproto"))


def main(argv):
    languages = LoadLanguages(base_dir=FLAGS.lang)
    regions = LoadRegions(base_dir=FLAGS.lang)

    if FLAGS.samples:
        assert len(argv) > 1, "No METADATA.pb files specified"
        line_to_lang_name = {}
        for l in languages:
            line = 'languages: "{code}"'.format(code=languages[l].id)
            line_to_lang_name[line] = languages[l].name
        samples = {}
        for sample_filename in os.listdir(FLAGS.samples):
            key = os.path.splitext(os.path.basename(sample_filename))[0]
            samples[key] = os.path.join(FLAGS.samples, sample_filename)
        for path in argv[1:]:
            family = _ReadProto(fonts_public_pb2.FamilyProto(), path)
            if (
                True
            ):  # len(family.languages) == 0 or family.name == 'Noto Sans Tamil Supplement':
                key = family.name.replace(" ", "")
                if key not in samples:
                    print("Family not found in samples: " + family.name)
                    continue
                with open(samples[key], "r") as f:
                    sample_data = yaml.safe_load(f)
                    sample_text = fonts_public_pb2.SampleTextProto()
                    sample_text.masthead_full = sample_data["masthead_full"]
                    sample_text.masthead_partial = sample_data["masthead_partial"]
                    sample_text.styles = sample_data["styles"]
                    sample_text.tester = sample_data["tester"]
                    sample_text.poster_sm = sample_data["poster_sm"]
                    sample_text.poster_md = sample_data["poster_md"]
                    sample_text.poster_lg = sample_data["poster_lg"]
                    family.sample_text.MergeFrom(sample_text)
                    _WriteProto(family, path, comments=line_to_lang_name)

    if not FLAGS.udhrs:
        return

    if FLAGS.udhrs.endswith(".yaml"):
        with open(FLAGS.udhrs, "r") as f:
            data = yaml.safe_load(f)
            for translation, meta in data.items():
                if "lang_full" not in meta or meta["lang_full"] not in [
                    "ccp-Beng-IN",
                    "lad-Hebr-IL",
                ]:
                    continue
                language = meta["lang"]
                if language.startswith("und-"):
                    continue
                script = (
                    re.search(r".*-(.*)-.*", meta["lang_full"]).group(1)
                    if "script" not in meta
                    else meta["script"]
                )
                key = language + "_" + script
                iso639_3 = meta["lang_639_3"]
                iso15924 = script
                name = (
                    meta["name_lang"] if "name_udhr" not in meta else meta["name_udhr"]
                )
                udhr = Udhr(
                    key=key,
                    iso639_3=iso639_3,
                    iso15924=iso15924,
                    bcp47=key,
                    direction=None,
                    ohchr=None,
                    stage=4,
                    loc=None,
                    name=name,
                )
                udhr.LoadArticleOne(translation)

                language = _GetLanguageForUdhr(languages, udhr)
                if not language.HasField("sample_text"):
                    language.sample_text.MergeFrom(udhr.GetSampleTexts())
                if "name_autonym" in meta and not language.HasField("autonym"):
                    language.autonym = meta["name_autonym"].strip()
                _WriteProto(
                    language,
                    os.path.join(FLAGS.lang, "languages", language.id + ".textproto"),
                )

    elif FLAGS.udhrs.endswith(".csv"):
        with open(FLAGS.udhrs, newline="") as csvfile:
            reader = csv.reader(csvfile, delimiter=",", quotechar='"')
            head = next(reader)
            index_id = head.index("id")
            index_name = head.index("language")
            index_historical = head.index("historical")
            index_sample = head.index("SAMPLE")
            for row in reader:
                id = row[index_id]
                if id in languages:
                    language = languages[row[index_id]]
                else:
                    language = fonts_public_pb2.LanguageProto()
                    language.id = id
                    language.language, language.script = id.split("_")
                    language.name = row[index_name]
                historical = row[index_historical] == "X"
                if language.historical != historical:
                    if historical:
                        language.historical = True
                    else:
                        language.ClearField("historical")
                sample = row[index_sample]
                if sample and not sample.startswith("http"):
                    udhr = Udhr(
                        key=id,
                        iso639_3=language.language,
                        iso15924=language.script,
                        bcp47=id,
                        direction=None,
                        ohchr=None,
                        stage=4,
                        loc=None,
                        name=None,
                    )
                    udhr.LoadArticleOne(sample)
                    if not language.HasField("sample_text"):
                        language.sample_text.MergeFrom(udhr.GetSampleTexts())
                _WriteProto(
                    language,
                    os.path.join(FLAGS.lang, "languages", language.id + ".textproto"),
                )

    elif os.path.isdir(FLAGS.udhrs):
        for udhr_path in glob.glob(os.path.join(FLAGS.udhrs, "*")):
            if udhr_path.endswith("index.xml") or os.path.basename(
                udhr_path
            ).startswith("status"):
                continue
            udhr_data = etree.parse(udhr_path)
            head = udhr_data.getroot()
            for name, value in head.attrib.items():
                if re.search(r"\{.*\}lang", name):
                    bcp47 = value.replace("-", "_")
            udhr = Udhr(
                key=head.get("key"),
                iso639_3=head.get("iso639-3"),
                iso15924=head.get("iso15924"),
                bcp47=bcp47,
                direction=head.get("dir"),
                ohchr=None,
                stage=4,
                loc=None,
                name=head.get("n"),
            )
            udhr.Parse(udhr_data)

            language = _GetLanguageForUdhr(languages, udhr)
            if language.id in languages or language.HasField("sample_text"):
                continue
            language.sample_text.MergeFrom(udhr.GetSampleTexts())
            _WriteProto(
                language,
                os.path.join(FLAGS.lang, "languages", language.id + ".textproto"),
            )

    else:
        raise Exception("Unsupported input type for --udhrs: " + FLAGS.udhrs)


if __name__ == "__main__":
    app.run(main)
