import argparse

from typing import List

"""
    Takes in one of the po files in resources/i18n/[LANG_CODE]/cura.po and updates it with translations from a 
    new po file without changing the translation ordering. 
    This script should be used when we get a po file that has updated translations but is no longer correctly ordered 
    so the merge becomes messy.
    
    If you are importing files from lionbridge/smartling use lionbridge_import.py.
    
    Note: This does NOT include new strings, it only UPDATES existing strings   
"""


class Msg:
    def __init__(self, msgctxt: str = "", msgid: str = "", msgstr: str = "") -> None:
        self.msgctxt = msgctxt
        self.msgid = msgid
        self.msgstr = msgstr

    def __str__(self):
        return self.msgctxt + self.msgid + self.msgstr


def parsePOFile(filename: str) -> List[Msg]:
    messages = []
    with open(filename) as f:
        iterator = iter(f.readlines())
        for line in iterator:
            if line.startswith("msgctxt"):
                #  Start of a translation item block
                msg = Msg()
                msg.msgctxt = line

                while True:
                    line = next(iterator)
                    if line.startswith("msgid"):
                        msg.msgid = line
                        break

                while True:
                    #  msgstr can be split over multiple lines
                    line = next(iterator)
                    if line == "\n":
                        break
                    if line.startswith("msgstr"):
                        msg.msgstr = line
                    else:
                        msg.msgstr += line

                messages.append(msg)

        return messages


def getDifferentMessages(messages_original: List[Msg], messages_new: List[Msg]) -> List[Msg]:
    #  Return messages that have changed in messages_new
    different_messages = []

    for m_new in messages_new:
        for m_original in messages_original:
            if m_new.msgstr != m_original.msgstr \
                    and m_new.msgid == m_original.msgid and m_new.msgctxt == m_original.msgctxt \
                    and m_new.msgid != 'msgid ""\n':
                different_messages.append(m_new)

    return different_messages


def updatePOFile(input_filename: str, output_filename: str, messages: List[Msg]) -> None:
    # Takes a list of changed messages and writes a copy of input file with updated message strings
    with open(input_filename, "r") as input_file, open(output_filename, "w") as output_file:
        iterator = iter(input_file.readlines())
        for line in iterator:
            output_file.write(line)
            if line.startswith("msgctxt"):
                #  Start of translation block
                msgctxt = line

                msgid = next(iterator)
                output_file.write(msgid)

                #  Check for updated version of msgstr
                message = list(filter(lambda m: m.msgctxt == msgctxt and m.msgid == msgid, messages))
                if message and message[0]:
                    #  Write update translation
                    output_file.write(message[0].msgstr)

                    # Skip lines until next translation. This should skip multiline msgstr
                    while True:
                        line = next(iterator)
                        if line == "\n":
                            output_file.write(line)
                            break


if __name__ == "__main__":
    print("********************************************************************************************************************")
    print("This creates a new file 'updated.po' that is a copy of original_file with any changed translations from updated_file")
    print("This does not change the order of translations")
    print("This does not include new translations, only existing changed translations")
    print("Do not use this to import lionbridge/smarting translations")
    print("********************************************************************************************************************")
    parser = argparse.ArgumentParser(description="Update po file with translations from new po file. This ")
    parser.add_argument("original_file", type=str, help="Input .po file inside resources/i18n/[LANG]/")
    parser.add_argument("updated_file", type=str, help="Input .po file with updated translations added")
    args = parser.parse_args()

    messages_updated = parsePOFile(args.updated_file)
    messages_original = parsePOFile(args.original_file)
    different_messages = getDifferentMessages(messages_original, messages_updated)
    updatePOFile(args.original_file, "updated.po", different_messages)