/*
    SPDX-FileCopyrightText: 2026 Igor Mironchik <igor.mironchik@gmail.com>
    SPDX-License-Identifier: MIT
*/

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

std::string codeToString(const std::string &code)
{
    size_t size = code.length();

    std::string res;

    size_t i = 2;

    bool first = true;

    while (size) {
        const auto c = code.substr(i, 4);
        size -= 6;
        i += 6;

        if (first) {
            first = false;
            res += "u\"\\x" + c;
        } else {
            res += "\\x" + c;
        }
    }

    res += "\"";

    return res;
}

int main()
{
    try {
        std::ifstream in("entities.json");

        if (in.good()) {
            std::ofstream out("entities_map.h");

            // REUSE-IgnoreStart

            out << "/*\n";
            out << "    SPDX-FileCopyrightText: 2026 Igor Mironchik <igor.mironchik@gmail.com>\n";
            out << "    SPDX-License-Identifier: MIT\n";
            out << "*/\n";
            out << "\n// This file is autogenerated.\n\n";
            out << "#ifndef MD4QT_ENTITIES_MAP_H_INCLUDED\n";
            out << "#define MD4QT_ENTITIES_MAP_H_INCLUDED\n\n";
            out << "#include <QHash>\n";
            out << "#include <QString>\n\n";
            out << "namespace MD\n";
            out << "{\n\n";
            out << "extern const QHash<QString, QString> s_entityMap;\n\n";
            out << "} /* namespace MD */\n\n#endif // MD4QT_ENTITIES_MAP_H_INCLUDED\n";

            out.close();

            out.open("entities_map.cpp");

            out << "/*\n";
            out << "    SPDX-FileCopyrightText: 2026 Igor Mironchik <igor.mironchik@gmail.com>\n";
            out << "    SPDX-License-Identifier: MIT\n";
            out << "*/\n";
            out << "\n// This file is autogenerated.\n\n";
            out << "#include \"entities_map.h\"\n\n";
            out << "namespace MD\n";
            out << "{\n\n";
            out << "const QHash<QString, QString> s_entityMap = {";

            // REUSE-IgnoreEnd

            bool first = true;

            for (std::string line; std::getline(in, line);) {
                const auto firstQuote = line.find("\"");

                if (firstQuote != std::string::npos) {
                    const auto secondQuote = line.find("\"", firstQuote + 1);

                    const auto name = line.substr(firstQuote + 1, secondQuote - firstQuote - 1);

                    const auto lastQuote = line.rfind("\"");

                    const auto prevLastQuote = line.rfind("\"", lastQuote - 1);

                    const auto code = line.substr(prevLastQuote + 1, lastQuote - prevLastQuote - 1);

                    if (out.good()) {
                        if (!first) {
                            out << ",\n    ";
                        }

                        out << "{QStringLiteral(\"" << name << "\"), QString::fromUtf16(" << codeToString(code) << ")}";
                    } else {
                        std::cout << "Unable to create file \"entities.hpp\"\n" << std::endl;

                        return -1;
                    }

                    first = false;
                }
            }

            out << "};\n\n} /* namespace MD */\n";
        } else {
            std::cout << "Unable to open file \"entities.json\"" << std::endl;

            return -1;
        }
    } catch (const std::logic_error &x) {
        std::cout << x.what() << std::endl;

        return -1;
    }
}
