#
# Copyright 2003-2008 Zuza Software Foundation
#
# This file is part of translate.
#
# translate is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# translate is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#

"""
Convert an OpenOffice.org (SDF) localization file to XLIFF localization files.

See: http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/oo2po.html
for examples and usage instructions.
"""

import logging

from translate.convert import convert
from translate.storage import oo, xliff

# TODO: support using one GSI file as template, another as input (for when English is in one and translation in another)

logger = logging.getLogger(__name__)


class oo2xliff:
    def __init__(
        self, sourcelanguage, targetlanguage, blankmsgstr=False, long_keys=False
    ) -> None:
        """Construct an oo2xliff converter for the specified languages."""
        self.sourcelanguage = sourcelanguage
        self.targetlanguage = targetlanguage
        self.blankmsgstr = blankmsgstr
        self.long_keys = long_keys

    @staticmethod
    def maketargetunit(part1, part2, translators_comment, key, subkey):
        """Makes a base unit (.po or XLIFF) out of a subkey of two parts."""
        # TODO: Do better
        text1 = getattr(part1, subkey)
        if not text1:
            return None
        text2 = getattr(part2, subkey)

        unit = xliff.xliffunit(text1)
        unit.target = text2
        if unit.target:
            unit.markfuzzy(False)
        else:
            unit.markfuzzy(True)
        unit.setid(f"{key}.{subkey}")
        if getattr(translators_comment, subkey).strip():
            unit.addnote(getattr(translators_comment, subkey), origin="developer")
        return unit

    def convertelement(self, theoo):
        """Convert an oo element into a list of base units (.po or XLIFF)."""
        if self.sourcelanguage in theoo.languages:
            part1 = theoo.languages[self.sourcelanguage]
        else:
            logger.error(
                "%s language not found: %s",
                "/".join(theoo.lines[0].getkey()),
                self.sourcelanguage,
            )
            return []
        if self.blankmsgstr:
            # use a blank part2
            part2 = oo.ooline()
        elif self.targetlanguage in theoo.languages:
            part2 = theoo.languages[self.targetlanguage]
        else:
            # if the language doesn't exist, the translation is missing ... so make it blank
            part2 = oo.ooline()
        if "x-comment" in theoo.languages:
            translators_comment = theoo.languages["x-comment"]
        else:
            translators_comment = oo.ooline()
        key = oo.makekey(part1.getkey(), self.long_keys)
        unitlist = []
        for subkey in ("text", "quickhelptext", "title"):
            unit = self.maketargetunit(part1, part2, translators_comment, key, subkey)
            if unit is not None:
                unitlist.append(unit)
        return unitlist

    def convertstore(self, theoofile, duplicatestyle="msgctxt"):
        """Converts an entire oo file to a base class format (.po or XLIFF)."""
        thetargetfile = xliff.xlifffile()
        thetargetfile.setsourcelanguage(self.sourcelanguage)
        thetargetfile.settargetlanguage(self.targetlanguage)
        # go through the oo and convert each element
        for theoo in theoofile.units:
            unitlist = self.convertelement(theoo)
            for unit in unitlist:
                thetargetfile.addunit(unit)
        return thetargetfile


class OOXliffConvertOptionParser(convert.ArchiveConvertOptionParser):
    """Custom option parser for OpenOffice to XLIFF conversion with verification."""

    def verifyoptions(self, options) -> None:
        """Verifies that the options are valid."""
        if not options.targetlanguage:
            raise ValueError("You must specify the target language.")


def convertoo(
    inputfile,
    outputfile,
    templates,
    pot=False,
    sourcelanguage=None,
    targetlanguage=None,
    duplicatestyle="msgctxt",
    multifilestyle="single",
) -> int:
    """Reads in stdin using inputstore class, converts using convertorclass, writes to stdout."""
    inputstore = oo.oofile()
    if hasattr(inputfile, "filename"):
        inputfilename = inputfile.filename
    else:
        inputfilename = "(input file name not known)"
    inputstore.filename = inputfilename
    inputstore.parse(inputfile.read())
    if not sourcelanguage:
        testlangtype = targetlanguage or (inputstore and inputstore.languages[0]) or ""
        sourcelanguage = "01" if testlangtype.isdigit() else "en-US"  # ty:ignore[unresolved-attribute]
    if sourcelanguage not in inputstore.languages:
        logger.warning(
            "sourcelanguage '%s' not found in inputfile '%s' (contains %s)",
            sourcelanguage,
            inputfilename,
            ", ".join(inputstore.languages),
        )
    if not pot and (targetlanguage and targetlanguage not in inputstore.languages):
        logger.warning(
            "targetlanguage '%s' not found in inputfile '%s' (contains %s)",
            targetlanguage,
            inputfilename,
            ", ".join(inputstore.languages),
        )
    convertor = oo2xliff(
        sourcelanguage,
        targetlanguage,
        blankmsgstr=pot,
        long_keys=(multifilestyle != "single"),
    )
    outputstore = convertor.convertstore(inputstore, duplicatestyle)
    if outputstore.isempty():
        return 0
    outputstore.serialize(outputfile)
    return 1


def main(argv=None) -> None:
    formats = (
        ("oo", ("xlf", convertoo)),
        ("sdf", ("xlf", convertoo)),
        ("oo", ("xliff", convertoo)),
        ("sdf", ("xliff", convertoo)),
    )
    # always treat the input as an archive unless it is a directory
    archiveformats = {(None, "input"): oo.oomultifile}
    parser = OOXliffConvertOptionParser(
        formats, usepots=False, description=__doc__, archiveformats=archiveformats
    )
    parser.add_option(
        "-l",
        "--language",
        dest="targetlanguage",
        default=None,
        help="set target language to extract from oo file (e.g. af-ZA)",
        metavar="LANG",
    )
    parser.add_option(
        "",
        "--source-language",
        dest="sourcelanguage",
        default=None,
        help="set source language code (default en-US)",
        metavar="LANG",
    )
    parser.add_option(
        "",
        "--nonrecursiveinput",
        dest="allowrecursiveinput",
        default=True,
        action="store_false",
        help="don't treat the input oo as a recursive store",
    )
    parser.add_duplicates_option()
    parser.add_multifile_option()
    parser.passthrough.append("sourcelanguage")
    parser.passthrough.append("targetlanguage")
    parser.run(argv)


if __name__ == "__main__":
    main()
