/*
 * Copyright 2013, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaHTTPConnection-JNI"
#include <utils/Log.h>

#include <binder/MemoryDealer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/ScopedLocalRef.h>

#include "android_media_MediaHTTPConnection.h"
#include "android_util_Binder.h"

#include "android_runtime/AndroidRuntime.h"
#include "jni.h"
#include "JNIHelp.h"

namespace android {

JMediaHTTPConnection::JMediaHTTPConnection(JNIEnv *env, jobject thiz)
    : mClass(NULL),
      mObject(NULL),
      mByteArrayObj(NULL) {
    jclass clazz = env->GetObjectClass(thiz);
    CHECK(clazz != NULL);

    mClass = (jclass)env->NewGlobalRef(clazz);
    mObject = env->NewWeakGlobalRef(thiz);

    mDealer = new MemoryDealer(kBufferSize, "MediaHTTPConnection");
    mMemory = mDealer->allocate(kBufferSize);

    ScopedLocalRef<jbyteArray> tmp(
            env, env->NewByteArray(JMediaHTTPConnection::kBufferSize));

    mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
}

JMediaHTTPConnection::~JMediaHTTPConnection() {
    JNIEnv *env = AndroidRuntime::getJNIEnv();

    env->DeleteGlobalRef(mByteArrayObj);
    mByteArrayObj = NULL;
    env->DeleteWeakGlobalRef(mObject);
    mObject = NULL;
    env->DeleteGlobalRef(mClass);
    mClass = NULL;
}

sp<IMemory> JMediaHTTPConnection::getIMemory() {
    return mMemory;
}

jbyteArray JMediaHTTPConnection::getByteArrayObj() {
    return mByteArrayObj;
}

}  // namespace android

using namespace android;

struct fields_t {
    jfieldID context;

    jmethodID readAtMethodID;
};

static fields_t gFields;

static sp<JMediaHTTPConnection> setObject(
        JNIEnv *env, jobject thiz, const sp<JMediaHTTPConnection> &conn) {
    sp<JMediaHTTPConnection> old =
        (JMediaHTTPConnection *)env->GetIntField(thiz, gFields.context);

    if (conn != NULL) {
        conn->incStrong(thiz);
    }
    if (old != NULL) {
        old->decStrong(thiz);
    }
    env->SetIntField(thiz, gFields.context, (int)conn.get());

    return old;
}

static sp<JMediaHTTPConnection> getObject(JNIEnv *env, jobject thiz) {
    return (JMediaHTTPConnection *)env->GetIntField(thiz, gFields.context);
}

static void android_media_MediaHTTPConnection_native_init(JNIEnv *env) {
    ScopedLocalRef<jclass> clazz(
            env, env->FindClass("android/media/MediaHTTPConnection"));
    CHECK(clazz.get() != NULL);

    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "I");
    CHECK(gFields.context != NULL);

    gFields.readAtMethodID = env->GetMethodID(clazz.get(), "readAt", "(J[BI)I");
}

static void android_media_MediaHTTPConnection_native_setup(
        JNIEnv *env, jobject thiz) {
    sp<JMediaHTTPConnection> conn = new JMediaHTTPConnection(env, thiz);

    setObject(env, thiz, conn);
}

static void android_media_MediaHTTPConnection_native_finalize(
        JNIEnv *env, jobject thiz) {
    setObject(env, thiz, NULL);
}

static jobject android_media_MediaHTTPConnection_native_getIMemory(
        JNIEnv *env, jobject thiz) {
    sp<JMediaHTTPConnection> conn = getObject(env, thiz);

    return javaObjectForIBinder(env, conn->getIMemory()->asBinder());
}

static jint android_media_MediaHTTPConnection_native_readAt(
        JNIEnv *env, jobject thiz, jlong offset, jint size) {
    sp<JMediaHTTPConnection> conn = getObject(env, thiz);

    if (size > JMediaHTTPConnection::kBufferSize) {
        size = JMediaHTTPConnection::kBufferSize;
    }

    jbyteArray byteArrayObj = conn->getByteArrayObj();

    jint n = env->CallIntMethod(
            thiz, gFields.readAtMethodID, offset, byteArrayObj, size);

    if (n > 0) {
        env->GetByteArrayRegion(
                byteArrayObj,
                0,
                n,
                (jbyte *)conn->getIMemory()->pointer());
    }

    return n;
}

static JNINativeMethod gMethods[] = {
    { "native_getIMemory", "()Landroid/os/IBinder;",
      (void *)android_media_MediaHTTPConnection_native_getIMemory },

    { "native_readAt", "(JI)I",
      (void *)android_media_MediaHTTPConnection_native_readAt },

    { "native_init", "()V",
      (void *)android_media_MediaHTTPConnection_native_init },

    { "native_setup", "()V",
      (void *)android_media_MediaHTTPConnection_native_setup },

    { "native_finalize", "()V",
      (void *)android_media_MediaHTTPConnection_native_finalize },
};

int register_android_media_MediaHTTPConnection(JNIEnv *env) {
    return AndroidRuntime::registerNativeMethods(env,
                "android/media/MediaHTTPConnection", gMethods, NELEM(gMethods));
}

