#include <jni.h>
#include <stdint.h>
#include <stdlib.h>

#include "obfuscate.h"
#include "obfuscate_file.h"

static jint throw_illegal_state(JNIEnv *env, const char *msg)
{
	jclass cls = (*env)->FindClass(env, "java/lang/IllegalStateException");
	if (cls != NULL)
		(*env)->ThrowNew(env, cls, msg);
	return OBF_ERR_NULL;
}

JNIEXPORT jint JNICALL
Java_com_foxx_androidcast_entitlements_EntitlementNativeBridge_nativeReadFrom(
	JNIEnv *env, jclass clazz, jstring path, jlong key, jlongArray out_val)
{
	const char *cpath;
	uint64_t decoded = 0;
	int32_t rv;
	jlong slot;

	(void)clazz;
	if (path == NULL || out_val == NULL)
		return throw_illegal_state(env, "path or out_val is null");

	cpath = (*env)->GetStringUTFChars(env, path, NULL);
	if (cpath == NULL)
		return OBF_ERR_IO;

	rv = read_from(cpath, (uint64_t)key, &decoded);
	(*env)->ReleaseStringUTFChars(env, path, cpath);
	if (rv != OBF_OK)
		return rv;

	slot = (jlong)decoded;
	(*env)->SetLongArrayRegion(env, out_val, 0, 1, &slot);
	return OBF_OK;
}

JNIEXPORT jint JNICALL
Java_com_foxx_androidcast_entitlements_EntitlementNativeBridge_nativeWriteTo(
	JNIEnv *env, jclass clazz, jstring path, jlong val, jlong key)
{
	const char *cpath;
	int32_t rv;

	(void)clazz;
	if (path == NULL)
		return throw_illegal_state(env, "path is null");

	cpath = (*env)->GetStringUTFChars(env, path, NULL);
	if (cpath == NULL)
		return OBF_ERR_IO;

	rv = write_to(cpath, (uint64_t)val, (uint64_t)key);
	(*env)->ReleaseStringUTFChars(env, path, cpath);
	return rv;
}

JNIEXPORT jint JNICALL
Java_com_foxx_androidcast_entitlements_EntitlementNativeBridge_nativeDecode(
	JNIEnv *env, jclass clazz, jlong encoded_val, jlong key, jlongArray out_val)
{
	uint64_t decoded = 0;
	int32_t rv;
	jlong slot;

	(void)clazz;
	if (out_val == NULL)
		return throw_illegal_state(env, "out_val is null");

	rv = decode((uint64_t)encoded_val, (uint64_t)key, &decoded);
	if (rv != OBF_OK)
		return rv;

	slot = (jlong)decoded;
	(*env)->SetLongArrayRegion(env, out_val, 0, 1, &slot);
	return OBF_OK;
}

JNIEXPORT jint JNICALL
Java_com_foxx_androidcast_entitlements_EntitlementNativeBridge_nativeEncode(
	JNIEnv *env, jclass clazz, jlong val, jlong key, jlongArray out_encoded)
{
	uint64_t encoded = 0;
	int32_t rv;
	jlong slot;

	(void)clazz;
	if (out_encoded == NULL)
		return throw_illegal_state(env, "out_encoded is null");

	rv = encode((uint64_t)val, (uint64_t)key, &encoded);
	if (rv != OBF_OK)
		return rv;

	slot = (jlong)encoded;
	(*env)->SetLongArrayRegion(env, out_encoded, 0, 1, &slot);
	return OBF_OK;
}
