/*
 * JNI bridge to nibtools' nibconv — converts a downloaded NIB/NBZ disk dump
 * (raw GCR preservation format) into a G64/D64 image VICE can attach.
 *
 * Without nibtools source (stub mode, HAVE_NIBTOOLS unset):
 *   convertDiskImage() always returns false. The "Download Disks" feature
 *   is unavailable but the rest of the app builds and runs normally.
 *
 * With nibtools source (HAVE_NIBTOOLS=1, set automatically by CMakeLists.txt
 * when nibtools-libs/<abi>/libnibtools.a exists):
 *   nibtools_nibconv_main() — nibconv's own main(), renamed at compile time
 *   (see build_nibtools.sh) — runs the real conversion. It is run on a
 *   throwaway pthread rather than the calling JNI thread: nibconv calls
 *   exit() on malformed input (e.g. a truncated download), and exit() is
 *   wrapped below to pthread_exit() instead of killing the whole app
 *   process. Isolating that to a disposable, JNI-unattached thread means a
 *   bad conversion just fails this one call instead of detaching the
 *   caller's JNI thread from underneath it.
 */

#include <jni.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_NIBTOOLS

extern int nibtools_nibconv_main(int argc, char **argv);

struct conv_args {
    char *in_path;
    char *out_path;
    int   result;
};

static void *run_nibconv(void *arg) {
    struct conv_args *a = (struct conv_args *)arg;
    char *argv[3] = { "nibconv", a->in_path, a->out_path };
    a->result = nibtools_nibconv_main(3, argv);
    return NULL;
}

/* Redirects nibconv's error-path exit() calls so they only terminate the
 * throwaway conversion thread above, never the whole process. */
void __wrap_exit(int status) {
    pthread_exit((void *)(long)status);
}

#endif /* HAVE_NIBTOOLS */

JNIEXPORT jboolean JNICALL
Java_de_ladkau_schwertundmagieonpebblecompanionapp_C64Engine_convertDiskImage(
    JNIEnv *env, jobject thiz, jstring inPath, jstring outPath)
{
    (void)thiz;
#ifdef HAVE_NIBTOOLS
    const char *inC  = (*env)->GetStringUTFChars(env, inPath, NULL);
    const char *outC = (*env)->GetStringUTFChars(env, outPath, NULL);

    struct conv_args args = { strdup(inC), strdup(outC), -1 };

    (*env)->ReleaseStringUTFChars(env, inPath, inC);
    (*env)->ReleaseStringUTFChars(env, outPath, outC);

    pthread_t t;
    pthread_create(&t, NULL, run_nibconv, &args);
    pthread_join(t, NULL);

    free(args.in_path);
    free(args.out_path);
    return args.result == 0 ? JNI_TRUE : JNI_FALSE;
#else
    (void)env; (void)inPath; (void)outPath;
    return JNI_FALSE;
#endif
}
