/* Copyright 2017 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

#include "./decoder_jni.h"

#include <new>

#include <brotli/decode.h>

namespace {
/* A structure used to persist the decoder's state in between calls. */
typedef struct DecoderHandle {
  BrotliDecoderState* state;

  jobject dictionary_refs[15];
  size_t dictionary_count;

  uint8_t* input_start;
  size_t input_offset;
  size_t input_length;
} DecoderHandle;

/* Obtain handle from opaque pointer. */
DecoderHandle* getHandle(void* opaque) {
  return static_cast<DecoderHandle*>(opaque);
}

}  /* namespace */

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Creates a new Decoder.
 *
 * Cookie to address created decoder is stored in out_cookie. In case of failure
 * cookie is 0.
 *
 * @param ctx {out_cookie, in_directBufferSize} tuple
 * @returns direct ByteBuffer if directBufferSize is not 0; otherwise null
 */
JNIEXPORT jobject JNICALL
Java_org_brotli_wrapper_dec_DecoderJNI_nativeCreate(
    JNIEnv* env, jobject /*jobj*/, jlongArray ctx) {
  bool ok = true;
  DecoderHandle* handle = nullptr;
  jlong context[3];
  env->GetLongArrayRegion(ctx, 0, 3, context);
  size_t input_size = context[1];
  context[0] = 0;
  context[2] = 0;
  handle = new (std::nothrow) DecoderHandle();
  ok = !!handle;

  if (ok) {
    for (int i = 0; i < 15; ++i) {
      handle->dictionary_refs[i] = nullptr;
    }
    handle->dictionary_count = 0;
    handle->input_offset = 0;
    handle->input_length = 0;
    handle->input_start = nullptr;

    if (input_size == 0) {
      ok = false;
    } else {
      handle->input_start = new (std::nothrow) uint8_t[input_size];
      ok = !!handle->input_start;
    }
  }

  if (ok) {
    handle->state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
    ok = !!handle->state;
  }

  if (ok) {
    /* TODO: future versions (e.g. when 128-bit architecture comes)
                     might require thread-safe cookie<->handle mapping. */
    context[0] = reinterpret_cast<jlong>(handle);
  } else if (!!handle) {
    if (!!handle->input_start) delete[] handle->input_start;
    delete handle;
  }

  env->SetLongArrayRegion(ctx, 0, 3, context);

  if (!ok) {
    return nullptr;
  }

  return env->NewDirectByteBuffer(handle->input_start, input_size);
}

/**
 * Push data to decoder.
 *
 * status codes:
 *  - 0 error happened
 *  - 1 stream is finished, no more input / output expected
 *  - 2 needs more input to process further
 *  - 3 needs more output to process further
 *  - 4 ok, can proceed further without additional input
 *
 * @param ctx {in_cookie, out_status} tuple
 * @param input_length number of bytes provided in input or direct input;
 *                     0 to process further previous input
 */
JNIEXPORT void JNICALL
Java_org_brotli_wrapper_dec_DecoderJNI_nativePush(
    JNIEnv* env, jobject /*jobj*/, jlongArray ctx, jint input_length) {
  jlong context[3];
  env->GetLongArrayRegion(ctx, 0, 3, context);
  DecoderHandle* handle = getHandle(reinterpret_cast<void*>(context[0]));
  context[1] = 0;  /* ERROR */
  context[2] = 0;
  env->SetLongArrayRegion(ctx, 0, 3, context);

  if (input_length != 0) {
    /* Still have unconsumed data. Workflow is broken. */
    if (handle->input_offset < handle->input_length) {
      return;
    }
    handle->input_offset = 0;
    handle->input_length = input_length;
  }

  /* Actual decompression. */
  const uint8_t* in = handle->input_start + handle->input_offset;
  size_t in_size = handle->input_length - handle->input_offset;
  size_t out_size = 0;
  BrotliDecoderResult status = BrotliDecoderDecompressStream(
      handle->state, &in_size, &in, &out_size, nullptr, nullptr);
  handle->input_offset = handle->input_length - in_size;
  switch (status) {
    case BROTLI_DECODER_RESULT_SUCCESS:
      /* Bytes after stream end are not allowed. */
      context[1] = (handle->input_offset == handle->input_length) ? 1 : 0;
      break;

    case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
      context[1] = 2;
      break;

    case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
      context[1] = 3;
      break;

    default:
      context[1] = 0;
      break;
  }
  context[2] = BrotliDecoderHasMoreOutput(handle->state) ? 1 : 0;
  env->SetLongArrayRegion(ctx, 0, 3, context);
}

/**
 * Pull decompressed data from decoder.
 *
 * @param ctx {in_cookie, out_status} tuple
 * @returns direct ByteBuffer; all the produced data MUST be consumed before
 *          any further invocation; null in case of error
 */
JNIEXPORT jobject JNICALL
Java_org_brotli_wrapper_dec_DecoderJNI_nativePull(
    JNIEnv* env, jobject /*jobj*/, jlongArray ctx) {
  jlong context[3];
  env->GetLongArrayRegion(ctx, 0, 3, context);
  DecoderHandle* handle = getHandle(reinterpret_cast<void*>(context[0]));
  size_t data_length = 0;
  const uint8_t* data = BrotliDecoderTakeOutput(handle->state, &data_length);
  bool hasMoreOutput = !!BrotliDecoderHasMoreOutput(handle->state);
  if (hasMoreOutput) {
    context[1] = 3;
  } else if (BrotliDecoderIsFinished(handle->state)) {
    /* Bytes after stream end are not allowed. */
    context[1] = (handle->input_offset == handle->input_length) ? 1 : 0;
  } else {
    /* Can proceed, or more data is required? */
    context[1] = (handle->input_offset == handle->input_length) ? 2 : 4;
  }
  context[2] = hasMoreOutput ? 1 : 0;
  env->SetLongArrayRegion(ctx, 0, 3, context);
  return env->NewDirectByteBuffer(const_cast<uint8_t*>(data), data_length);
}

/**
 * Releases all used resources.
 *
 * @param ctx {in_cookie} tuple
 */
JNIEXPORT void JNICALL
Java_org_brotli_wrapper_dec_DecoderJNI_nativeDestroy(
    JNIEnv* env, jobject /*jobj*/, jlongArray ctx) {
  jlong context[3];
  env->GetLongArrayRegion(ctx, 0, 3, context);
  DecoderHandle* handle = getHandle(reinterpret_cast<void*>(context[0]));
  BrotliDecoderDestroyInstance(handle->state);
  for (size_t i = 0; i < handle->dictionary_count; ++i) {
    env->DeleteGlobalRef(handle->dictionary_refs[i]);
  }
  delete[] handle->input_start;
  delete handle;
}

JNIEXPORT jboolean JNICALL
Java_org_brotli_wrapper_dec_DecoderJNI_nativeAttachDictionary(
    JNIEnv* env, jobject /*jobj*/, jlongArray ctx, jobject dictionary) {
  jlong context[3];
  env->GetLongArrayRegion(ctx, 0, 3, context);
  DecoderHandle* handle = getHandle(reinterpret_cast<void*>(context[0]));
  jobject ref = nullptr;
  uint8_t* address = nullptr;
  jlong capacity = 0;

  bool ok = true;
  if (ok && !dictionary) {
    ok = false;
  }
  if (ok && handle->dictionary_count >= 15) {
    ok = false;
  }
  if (ok) {
    ref = env->NewGlobalRef(dictionary);
    ok = !!ref;
  }
  if (ok) {
    handle->dictionary_refs[handle->dictionary_count] = ref;
    handle->dictionary_count++;
    address = static_cast<uint8_t*>(env->GetDirectBufferAddress(ref));
    ok = !!address;
  }
  if (ok) {
    capacity = env->GetDirectBufferCapacity(ref);
    ok = (capacity > 0) && (capacity < (1 << 30));
  }
  if (ok) {
    size_t size = static_cast<size_t>(capacity);
    ok = !!BrotliDecoderAttachDictionary(handle->state,
        BROTLI_SHARED_DICTIONARY_RAW, size, address);
  }

  return static_cast<jboolean>(ok);
}

#ifdef __cplusplus
}
#endif
