/*
 * Copyright 2025 Rive
 */

#if defined(__EMSCRIPTEN__)

#include "common/rive_wasm_app.hpp"

#include "common/test_harness.hpp"
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#include <sstream>
#include <vector>

EM_JS(char*, get_window_location, (), {
    var jsString = window.location.href;
    var lengthBytes = lengthBytesUTF8(jsString) + 1;
    var stringOnWasmHeap = _malloc(lengthBytes);
    stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
    return stringOnWasmHeap;
});

EM_JS(char*, get_window_location_hash, (), {
    var jsString = window.location.hash.substring(1);
    var lengthBytes = lengthBytesUTF8(jsString) + 1;
    var stringOnWasmHeap = _malloc(lengthBytes);
    stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
    return stringOnWasmHeap;
});

static void split_string(const std::string& str,
                         const std::string& delimiter,
                         std::vector<std::string>& result)
{
    size_t start = 0;
    size_t end;

    while ((end = str.find(delimiter, start)) != std::string::npos)
    {
        if (end > start)
        {
            result.push_back(str.substr(start, end - start));
        }
        start = end + delimiter.length();
    }

    if (str.length() > start)
    {
        // Add the last piece
        result.push_back(str.substr(start));
    }
}

int main()
{
    char* location = get_window_location();
    char* hash = get_window_location_hash();

    // Command line arguments are passed via the window location's hash string.
    //
    //   e.g., "http://localhost/my_app.html#--backend%20gl%20--another%20arg"
    //
    std::vector<std::string> hashStrs = {location};
    split_string(hash, "%20", hashStrs);

    free(hash);
    free(location);

    std::vector<const char*> hashArgs;
    for (const std::string& str : hashStrs)
    {
        hashArgs.push_back(str.c_str());
    }

    return rive_wasm_main(hashArgs.size(), hashArgs.data());
}

extern "C" void rive_print_message_on_server(const char* msg)
{
    // stdout and stderr get redirected here and forwarded to the server for
    // logging.
    static bool nested = false;
    if (nested)
    {
        // Avoid accidental infinite recursion in case anything gets printed
        // inside printMessageOnServer().
        // These messages will still make it to the browser's console.
        return;
    }
    nested = true;
    TestHarness::Instance().printMessageOnServer(msg);
    nested = false;
}

#endif
