/*
 * Copyright 2025 Rive
 */

#include "common/stacktrace.hpp"
#include <assert.h>

#if defined(NO_REDIRECT_OUTPUT) || defined(__EMSCRIPTEN__)

namespace stacktrace
{
void replace_signal_handlers(SignalFunc signalFunc,
                             ExitFunc atExitFunc) noexcept
{}
}; // namespace stacktrace

#else

#ifdef _WIN32
#include <Windows.h>
#include <dbghelp.h>
#else
#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <dlfcn.h>
#include <cxxabi.h>
#endif

#ifdef SYS_SIGNAL_H
#include <sys/signal.h>
#else
#include <signal.h>
#endif

#include <stdio.h>
#include <sstream>

static SignalFunc signalFunc;
static int signalRecurseLevel = 0;

// this is outside the namespace so we can use it as if it was defined by the
// c++ runtime
#if defined(SYS_SIGNAL_H) || defined(_WIN32)
const char* strsignal(int signo)
{
    switch (signo)
    {
        case SIGINT:
            return "SIGINT";
        case SIGILL:
            return "SIGILL";
        case SIGFPE:
            return "SIGFPE";
        case SIGSEGV:
            return "SIGSEGV";
        case SIGTERM:
            return "SIGTERM";
        case SIGBREAK:
            return "SIGBREAK";
        case SIGABRT:
            return "SIGABRT";
    }
    return "Unknown Signal";
}
#endif

namespace stacktrace
{
#if defined(_WIN32)
LONG WINAPI top_level_exception_handler(PEXCEPTION_POINTERS pExceptionInfo)
{
    std::stringstream f;

    HANDLE process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);

    // StackWalk64() may modify context record passed to it, so we will
    // use a copy.
    CONTEXT context_record = *pExceptionInfo->ContextRecord;
    // Initialize stack walking.
    STACKFRAME64 stack_frame;
    memset(&stack_frame, 0, sizeof(stack_frame));
#if defined(_WIN64)
    int machine_type = IMAGE_FILE_MACHINE_AMD64;
    stack_frame.AddrPC.Offset = context_record.Rip;
    stack_frame.AddrFrame.Offset = context_record.Rbp;
    stack_frame.AddrStack.Offset = context_record.Rsp;
#else
    int machine_type = IMAGE_FILE_MACHINE_I386;
    stack_frame.AddrPC.Offset = context_record.Eip;
    stack_frame.AddrFrame.Offset = context_record.Ebp;
    stack_frame.AddrStack.Offset = context_record.Esp;
#endif
    stack_frame.AddrPC.Mode = AddrModeFlat;
    stack_frame.AddrFrame.Mode = AddrModeFlat;
    stack_frame.AddrStack.Mode = AddrModeFlat;

    char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;

    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;

    while (StackWalk64(machine_type,
                       GetCurrentProcess(),
                       GetCurrentThread(),
                       &stack_frame,
                       &context_record,
                       NULL,
                       &SymFunctionTableAccess64,
                       &SymGetModuleBase64,
                       NULL))
    {

        DWORD64 displacement = 0;

        if (!SymFromAddr(process,
                         (DWORD64)stack_frame.AddrPC.Offset,
                         &displacement,
                         pSymbol))
        {
            continue;
        }

        IMAGEHLP_MODULE64 moduleInfo;
        ZeroMemory(&moduleInfo, sizeof(IMAGEHLP_MODULE64));
        moduleInfo.SizeOfStruct = sizeof(moduleInfo);

        if (::SymGetModuleInfo64(process, pSymbol->ModBase, &moduleInfo))
            f << moduleInfo.ModuleName << ": ";

        f << pSymbol->Name << " + 0x" << std::hex << displacement << std::endl;
    }

    signalFunc(f.str().c_str());

    // match to SymInitialize
    SymCleanup(process);

    return EXCEPTION_CONTINUE_SEARCH;
}

void build_stack(int signo)
{
    CONTEXT context;
    ZeroMemory(&context, sizeof(CONTEXT));
    RtlCaptureContext(&context);
    EXCEPTION_POINTERS exceptionPointers;
    ZeroMemory(&exceptionPointers, sizeof(EXCEPTION_POINTERS));
    exceptionPointers.ContextRecord = &context;
    top_level_exception_handler(&exceptionPointers);
}

static void handle_signal(int signo) noexcept
{
    // this is because we can accidently spam the signal handler if we can't
    // communicate with the server
    if (signo == SIGABRT)
    {
        if (++signalRecurseLevel > 1)
        {
            return;
        }
    }

    printf("Received signal %i (\"%s\")\n", signo, strsignal(signo));

    build_stack(signo);
    // set the signal handler to the original
    signal(signo, SIG_DFL);
    // re raise the signal
    raise(signo);
}

void replace_signal_handlers(SignalFunc inSignalFunc,
                             ExitFunc atExitFunc) noexcept
{
    assert(inSignalFunc);
    assert(atExitFunc);

    // signals can only use global vars
    signalFunc = inSignalFunc;

    SetUnhandledExceptionFilter(top_level_exception_handler);

    for (int i = 1; i <= SIGTERM; ++i)
    {
        signal(i, handle_signal);
    }
    // for windows SIGABRT is a higher number then SIGTERM, so make sure to
    // intercept it as well
    signal(SIGABRT, handle_signal);

    atexit(atExitFunc);
}
#else
#ifdef RIVE_ANDROID
// android is a little more complicated in that it requires specific compiler
// flags that i don't want to force us into, so we just do it the old way for
// now
static void handle_signal(int sigNum, siginfo_t* signalInfo, void* userContext)
{
    printf("Received signal %i (\"%s\")\n", sigNum, strsignal(sigNum));
    signal(sigNum, SIG_DFL);
    signalFunc(strsignal(sigNum));
    raise(sigNum);
}

#else // we are unix

static void handle_signal(int sigNum, siginfo_t* signalInfo, void* userContext)
{
    printf("Received signal %i (\"%s\")\n", sigNum, strsignal(sigNum));
    // this is because we can accidently spam the signal handler if we can't
    // communicate with the server
    if (sigNum == SIGABRT)
    {
        if (++signalRecurseLevel > 1)
        {
            return;
        }
    }

    std::stringstream f;

    void* stacktrace[1024];
    char** symbols;
    char stringBuff[1024];
    // this is technically unsafe since it uses malloc behind the scene but it's
    // way simpler then the alternative and this is just for testing anyway so
    // it's fine
    int numFrames = backtrace(stacktrace, 1024);
    symbols = backtrace_symbols(stacktrace, numFrames);
    for (int i = 1; i < numFrames; i++)
    {
        Dl_info dlInfo;
        if (dladdr(stacktrace[i], &dlInfo))
        {
            char* demangled = NULL;
            int status;
            demangled = abi::__cxa_demangle(dlInfo.dli_sname, NULL, 0, &status);
            snprintf(stringBuff,
                     sizeof(stringBuff),
                     "%d %s\n",
                     i,
                     status == 0 ? demangled : dlInfo.dli_sname);
            free(demangled);
        }
        else
        {
            snprintf(stringBuff,
                     sizeof(stringBuff),
                     "%d %p\n",
                     i,
                     stacktrace[i]);
        }

        f << stringBuff << symbols[i] << "\n";
    }

    free(symbols);

    // send stack to server
    signalFunc(f.str().c_str());

    exit(sigNum);
}
#endif
void replace_signal_handlers(SignalFunc inSignalFunc,
                             ExitFunc atExitFunc) noexcept
{
    assert(inSignalFunc);
    assert(atExitFunc);

    signalFunc = inSignalFunc;

    struct sigaction action;
    struct sigaction oldAction;
    action.sa_flags = SA_SIGINFO | SA_ONSTACK;
#if defined(__LP64__) && defined(__APPLE__)
    action.sa_flags |= SA_64REGSET;
#endif
    action.sa_sigaction = &handle_signal;

    for (int i = 1; i <= SIGTERM; ++i)
    {
        sigaction(i, &action, &oldAction);
    }

    atexit(atExitFunc);
}

#endif // defined _WIN32

}; // namespace stacktrace
#endif // defined(NO_REDIRECT_OUTPUT) || defined(__EMSCRIPTEN__)
