#!/usr/bin/env python3

#
# //===----------------------------------------------------------------------===//
# //
# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# // See https://llvm.org/LICENSE.txt for license information.
# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# //
# //===----------------------------------------------------------------------===//
#

import argparse
import os
import platform
import re
import sys
from libomputils import ScriptError, error


class TargetPlatform:
    """Convenience class for handling the target platform for configuration/compilation"""

    system_override = None
    """
    Target system name override by the user.
    It follows the conventions from https://docs.python.org/3/library/platform.html#platform.system
    """

    def set_system_override(override_system):
        """
        Set a system override for the target.
        Please follow the style from https://docs.python.org/3/library/platform.html#platform.system
        """
        TargetPlatform.system_override = override_system

    def system():
        """
        Target System name.
        It follows the conventions from https://docs.python.org/3/library/platform.html#platform.system
        """
        if TargetPlatform.system_override is None:
            return platform.system()
        return TargetPlatform.system_override


class ParseMessageDataError(ScriptError):
    """Convenience class for parsing message data file errors"""

    def __init__(self, filename, line, msg):
        super(ParseMessageDataError, self).__init__(msg)
        self.filename = filename
        self.line = line


def parse_error(filename, line, msg):
    raise ParseMessageDataError(filename, line, msg)


def display_language_id(inputFile):
    """Quickly parse file for LangId and print it"""
    regex = re.compile(r'^LangId\s+"([0-9]+)"')
    with open(inputFile, encoding="utf-8") as f:
        for line in f:
            m = regex.search(line)
            if not m:
                continue
            print(m.group(1))


class Message(object):
    special = {
        "n": "\n",
        "t": "\t",
    }

    def __init__(self, lineNumber, name, text):
        self.lineNumber = lineNumber
        self.name = name
        self.text = text

    def toSrc(self):
        if TargetPlatform.system().casefold() == "Windows".casefold():
            return re.sub(r"%([0-9])\$(s|l?[du])", r"%\1!\2!", self.text)
        return str(self.text)

    def toMC(self):
        retval = self.toSrc()
        for special, substitute in Message.special.items():
            retval = re.sub(r"\\{}".format(special), substitute, retval)
        return retval


class MessageData(object):
    """
    Convenience class representing message data parsed from i18n/* files

    Generate these objects using static create() factory method
    """

    sectionInfo = {
        "meta": {"short": "prp", "long": "meta", "set": 1, "base": 1 << 16},
        "strings": {"short": "str", "long": "strings", "set": 2, "base": 2 << 16},
        "formats": {"short": "fmt", "long": "formats", "set": 3, "base": 3 << 16},
        "messages": {"short": "msg", "long": "messages", "set": 4, "base": 4 << 16},
        "hints": {"short": "hnt", "long": "hints", "set": 5, "base": 5 << 16},
    }
    orderedSections = ["meta", "strings", "formats", "messages", "hints"]

    def __init__(self):
        self.filename = None
        self.sections = {}

    def getMeta(self, name):
        metaList = self.sections["meta"]
        for meta in metaList:
            if meta.name == name:
                return meta.text
        error(
            'No "{}" detected in meta data' " for file {}".format(name, self.filename)
        )

    @staticmethod
    def create(inputFile):
        """Creates MessageData object from inputFile"""
        data = MessageData()
        data.filename = os.path.abspath(inputFile)
        obsolete = 1
        sectionRegex = re.compile(r"-\*- ([a-zA-Z0-9_]+) -\*-")
        keyValueRegex = re.compile(r'([a-zA-Z_][a-zA-Z0-9_]*)\s+"(.*)"')
        moreValueRegex = re.compile(r'"(.*)"')

        with open(inputFile, "r", encoding="utf-8") as f:
            currentSection = None
            currentKey = None
            for lineNumber, line in enumerate(f, 1):
                line = line.strip()
                # Skip empty lines
                if not line:
                    continue
                # Skip comment lines
                if line.startswith("#"):
                    continue
                # Matched a section header
                match = sectionRegex.search(line)
                if match:
                    currentSection = match.group(1).lower()
                    if currentSection in data.sections:
                        parse_error(
                            inputFile,
                            lineNumber,
                            "section: {} already defined".format(currentSection),
                        )
                    data.sections[currentSection] = []
                    continue
                # Matched a Key "Value" line (most lines)
                match = keyValueRegex.search(line)
                if match:
                    if not currentSection:
                        parse_error(inputFile, lineNumber, "no section defined yet.")
                    key = match.group(1)
                    if key == "OBSOLETE":
                        key = "OBSOLETE{}".format(obsolete)
                        obsolete += 1
                    value = match.group(2)
                    currentKey = key
                    data.sections[currentSection].append(
                        Message(lineNumber, key, value)
                    )
                    continue
                # Matched a Continuation of string line
                match = moreValueRegex.search(line)
                if match:
                    value = match.group(1)
                    if not currentSection:
                        parse_error(inputFile, lineNumber, "no section defined yet.")
                    if not currentKey:
                        parse_error(inputFile, lineNumber, "no key defined yet.")
                    data.sections[currentSection][-1].text += value
                    continue
                # Unknown line syntax
                parse_error(inputFile, lineNumber, "bad line:\n{}".format(line))
        return data


def insert_header(f, data, commentChar="//"):
    f.write(
        "{0} Do not edit this file! {0}\n"
        "{0} The file was generated from"
        " {1} by {2}. {0}\n\n".format(
            commentChar,
            os.path.basename(data.filename),
            os.path.basename(__file__),
        )
    )


def generate_enum_file(enumFile, prefix, data):
    """Create the include file with message enums"""
    global g_sections
    with open(enumFile, "w") as f:
        insert_header(f, data)
        f.write(
            "enum {0}_id {1}\n"
            "\n"
            "    // A special id for absence of message.\n"
            "    {0}_null = 0,\n"
            "\n".format(prefix, "{")
        )
        for section in MessageData.orderedSections:
            messages = data.sections[section]
            info = MessageData.sectionInfo[section]
            shortName = info["short"]
            longName = info["long"]
            base = info["base"]
            setIdx = info["set"]
            f.write(
                "    // Set #{}, {}.\n"
                "    {}_{}_first = {},\n".format(
                    setIdx, longName, prefix, shortName, base
                )
            )
            for message in messages:
                f.write("    {}_{}_{},\n".format(prefix, shortName, message.name))
            f.write("    {}_{}_last,\n\n".format(prefix, shortName))
        f.write(
            "    {0}_xxx_lastest\n\n"
            "{1}; // enum {0}_id\n\n"
            "typedef enum {0}_id  {0}_id_t;\n\n\n"
            "// end of file //\n".format(prefix, "}")
        )


def generate_signature_file(signatureFile, data):
    """Create the signature file"""
    sigRegex = re.compile(r"(%[0-9]\$(s|l?[du]))")
    with open(signatureFile, "w") as f:
        f.write("// message catalog signature file //\n\n")
        for section in MessageData.orderedSections:
            messages = data.sections[section]
            longName = MessageData.sectionInfo[section]["long"]
            f.write("-*- {}-*-\n\n".format(longName.upper()))
            for message in messages:
                sigs = sorted(list(set([a for a, b in sigRegex.findall(message.text)])))
                i = 0
                # Insert empty placeholders if necessary
                while i != len(sigs):
                    num = i + 1
                    if not sigs[i].startswith("%{}".format(num)):
                        sigs.insert(i, "%{}$-".format(num))
                    else:
                        i += 1
                f.write("{:<40} {}\n".format(message.name, " ".join(sigs)))
            f.write("\n")
        f.write("// end of file //\n")


def generate_default_messages_file(defaultFile, prefix, data):
    """Create the include file with message strings organized"""
    with open(defaultFile, "w", encoding="utf-8") as f:
        insert_header(f, data)
        for section in MessageData.orderedSections:
            f.write(
                "static char const *\n"
                "__{}_default_{}[] =\n"
                "    {}\n"
                "        NULL,\n".format(prefix, section, "{")
            )
            messages = data.sections[section]
            for message in messages:
                f.write('        "{}",\n'.format(message.toSrc()))
            f.write("        NULL\n" "    {};\n\n".format("}"))
        f.write(
            "struct kmp_i18n_section {0}\n"
            "    int           size;\n"
            "    char const ** str;\n"
            "{1}; // struct kmp_i18n_section\n"
            "typedef struct kmp_i18n_section  kmp_i18n_section_t;\n\n"
            "static kmp_i18n_section_t\n"
            "__{2}_sections[] =\n"
            "    {0}\n"
            "        {0} 0, NULL {1},\n".format("{", "}", prefix)
        )

        for section in MessageData.orderedSections:
            messages = data.sections[section]
            f.write(
                "        {} {}, __{}_default_{} {},\n".format(
                    "{", len(messages), prefix, section, "}"
                )
            )
        numSections = len(MessageData.orderedSections)
        f.write(
            "        {0} 0, NULL {1}\n"
            "    {1};\n\n"
            "struct kmp_i18n_table {0}\n"
            "    int                   size;\n"
            "    kmp_i18n_section_t *  sect;\n"
            "{1}; // struct kmp_i18n_table\n"
            "typedef struct kmp_i18n_table  kmp_i18n_table_t;\n\n"
            "static kmp_i18n_table_t __kmp_i18n_default_table =\n"
            "    {0}\n"
            "        {3},\n"
            "        __{2}_sections\n"
            "    {1};\n\n"
            "// end of file //\n".format("{", "}", prefix, numSections)
        )


def generate_message_file_unix(messageFile, data):
    """
    Create the message file for Unix OSes

    Encoding is in UTF-8
    """
    with open(messageFile, "w", encoding="utf-8") as f:
        insert_header(f, data, commentChar="$")
        f.write('$quote "\n\n')
        for section in MessageData.orderedSections:
            setIdx = MessageData.sectionInfo[section]["set"]
            f.write(
                "$ ------------------------------------------------------------------------------\n"
                "$ {}\n"
                "$ ------------------------------------------------------------------------------\n\n"
                "$set {}\n\n".format(section, setIdx)
            )
            messages = data.sections[section]
            for num, message in enumerate(messages, 1):
                f.write('{} "{}"\n'.format(num, message.toSrc()))
            f.write("\n")
        f.write("\n$ end of file $")


def generate_message_file_windows(messageFile, data):
    """
    Create the message file for Windows OS

    Encoding is in UTF-16LE
    """
    language = data.getMeta("Language")
    langId = data.getMeta("LangId")
    with open(messageFile, "w", encoding="utf-16-le") as f:
        insert_header(f, data, commentChar=";")
        f.write("\nLanguageNames = ({0}={1}:msg_{1})\n\n".format(language, langId))
        f.write("FacilityNames=(\n")
        for section in MessageData.orderedSections:
            setIdx = MessageData.sectionInfo[section]["set"]
            shortName = MessageData.sectionInfo[section]["short"]
            f.write(" {}={}\n".format(shortName, setIdx))
        f.write(")\n\n")

        for section in MessageData.orderedSections:
            shortName = MessageData.sectionInfo[section]["short"]
            n = 0
            messages = data.sections[section]
            for message in messages:
                n += 1
                f.write(
                    "MessageId={}\n"
                    "Facility={}\n"
                    "Language={}\n"
                    "{}\n.\n\n".format(n, shortName, language, message.toMC())
                )
        f.write("\n; end of file ;")


def main():
    parser = argparse.ArgumentParser(description="Generate message data files")
    parser.add_argument(
        "--lang-id",
        action="store_true",
        help="Print language identifier of the message catalog source file",
    )
    parser.add_argument(
        "--prefix",
        default="kmp_i18n",
        help="Prefix to be used for all C identifiers (type and variable names)"
        " in enum and default message files.",
    )
    parser.add_argument("--enum", metavar="FILE", help="Generate enum file named FILE")
    parser.add_argument(
        "--default", metavar="FILE", help="Generate default messages file named FILE"
    )
    parser.add_argument(
        "--signature", metavar="FILE", help="Generate signature file named FILE"
    )
    parser.add_argument(
        "--message", metavar="FILE", help="Generate message file named FILE"
    )
    parser.add_argument(
        "--target-system-override",
        metavar="TARGET_SYSTEM_NAME",
        help="Target System override.\n"
        "By default the target system is the host system\n"
        "See possible values at https://docs.python.org/3/library/platform.html#platform.system",
    )
    parser.add_argument("inputfile")
    commandArgs = parser.parse_args()

    if commandArgs.lang_id:
        display_language_id(commandArgs.inputfile)
        return
    data = MessageData.create(commandArgs.inputfile)
    prefix = commandArgs.prefix
    if commandArgs.target_system_override:
        TargetPlatform.set_system_override(commandArgs.target_system_override)
    if commandArgs.enum:
        generate_enum_file(commandArgs.enum, prefix, data)
    if commandArgs.default:
        generate_default_messages_file(commandArgs.default, prefix, data)
    if commandArgs.signature:
        generate_signature_file(commandArgs.signature, data)
    if commandArgs.message:
        if TargetPlatform.system().casefold() == "Windows".casefold():
            generate_message_file_windows(commandArgs.message, data)
        else:
            generate_message_file_unix(commandArgs.message, data)


if __name__ == "__main__":
    try:
        main()
    except ScriptError as e:
        print("error: {}".format(e))
        sys.exit(1)

# end of file
