/*
 * Copyright 2017, 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 "JMedia2HTTPConnection"
#include <utils/Log.h>

#include <mediaplayer2/JavaVMHelper.h>
#include <mediaplayer2/JMedia2HTTPConnection.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/scoped_local_ref.h>

#include "log/log.h"
#include "jni.h"

namespace android {

static const size_t kBufferSize = 32768;

JMedia2HTTPConnection::JMedia2HTTPConnection(JNIEnv *env, jobject thiz) {
    mMedia2HTTPConnectionObj = env->NewGlobalRef(thiz);
    CHECK(mMedia2HTTPConnectionObj != NULL);

    ScopedLocalRef<jclass> media2HTTPConnectionClass(
            env, env->GetObjectClass(mMedia2HTTPConnectionObj));
    CHECK(media2HTTPConnectionClass.get() != NULL);

    mConnectMethod = env->GetMethodID(
            media2HTTPConnectionClass.get(),
            "connect",
            "(Ljava/lang/String;Ljava/lang/String;)Z");
    CHECK(mConnectMethod != NULL);

    mDisconnectMethod = env->GetMethodID(
            media2HTTPConnectionClass.get(),
            "disconnect",
            "()V");
    CHECK(mDisconnectMethod != NULL);

    mReadAtMethod = env->GetMethodID(
            media2HTTPConnectionClass.get(),
            "readAt",
            "(J[BI)I");
    CHECK(mReadAtMethod != NULL);

    mGetSizeMethod = env->GetMethodID(
            media2HTTPConnectionClass.get(),
            "getSize",
            "()J");
    CHECK(mGetSizeMethod != NULL);

    mGetMIMETypeMethod = env->GetMethodID(
            media2HTTPConnectionClass.get(),
            "getMIMEType",
            "()Ljava/lang/String;");
    CHECK(mGetMIMETypeMethod != NULL);

    mGetUriMethod = env->GetMethodID(
            media2HTTPConnectionClass.get(),
            "getUri",
            "()Ljava/lang/String;");
    CHECK(mGetUriMethod != NULL);

    ScopedLocalRef<jbyteArray> tmp(
        env, env->NewByteArray(kBufferSize));
    mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
    CHECK(mByteArrayObj != NULL);
}

JMedia2HTTPConnection::~JMedia2HTTPConnection() {
    JNIEnv *env = JavaVMHelper::getJNIEnv();
    env->DeleteGlobalRef(mMedia2HTTPConnectionObj);
    env->DeleteGlobalRef(mByteArrayObj);
}

bool JMedia2HTTPConnection::connect(
        const char *uri, const KeyedVector<String8, String8> *headers) {
    String8 tmp("");
    if (headers != NULL) {
        for (size_t i = 0; i < headers->size(); ++i) {
            tmp.append(headers->keyAt(i));
            tmp.append(String8(": "));
            tmp.append(headers->valueAt(i));
            tmp.append(String8("\r\n"));
        }
    }

    JNIEnv* env = JavaVMHelper::getJNIEnv();
    jstring juri = env->NewStringUTF(uri);
    jstring jheaders = env->NewStringUTF(tmp.string());

    jboolean ret =
        env->CallBooleanMethod(mMedia2HTTPConnectionObj, mConnectMethod, juri, jheaders);

    env->DeleteLocalRef(juri);
    env->DeleteLocalRef(jheaders);

    return (bool)ret;
}

void JMedia2HTTPConnection::disconnect() {
    JNIEnv* env = JavaVMHelper::getJNIEnv();
    env->CallVoidMethod(mMedia2HTTPConnectionObj, mDisconnectMethod);
}

ssize_t JMedia2HTTPConnection::readAt(off64_t offset, void *data, size_t size) {
    JNIEnv* env = JavaVMHelper::getJNIEnv();

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

    jint n = env->CallIntMethod(
            mMedia2HTTPConnectionObj, mReadAtMethod, (jlong)offset, mByteArrayObj, (jint)size);

    if (n > 0) {
        env->GetByteArrayRegion(
                mByteArrayObj,
                0,
                n,
                (jbyte *)data);
    }

    return n;
}

off64_t JMedia2HTTPConnection::getSize() {
    JNIEnv* env = JavaVMHelper::getJNIEnv();
    return (off64_t)(env->CallLongMethod(mMedia2HTTPConnectionObj, mGetSizeMethod));
}

status_t JMedia2HTTPConnection::getMIMEType(String8 *mimeType) {
    JNIEnv* env = JavaVMHelper::getJNIEnv();
    jstring jmime = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetMIMETypeMethod);
    jboolean flag = env->ExceptionCheck();
    if (flag) {
        env->ExceptionClear();
        return UNKNOWN_ERROR;
    }

    const char *str = env->GetStringUTFChars(jmime, 0);
    if (str != NULL) {
        *mimeType = String8(str);
    } else {
        *mimeType = "application/octet-stream";
    }
    env->ReleaseStringUTFChars(jmime, str);
    return OK;
}

status_t JMedia2HTTPConnection::getUri(String8 *uri) {
    JNIEnv* env = JavaVMHelper::getJNIEnv();
    jstring juri = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetUriMethod);
    jboolean flag = env->ExceptionCheck();
    if (flag) {
        env->ExceptionClear();
        return UNKNOWN_ERROR;
    }

    const char *str = env->GetStringUTFChars(juri, 0);
    *uri = String8(str);
    env->ReleaseStringUTFChars(juri, str);
    return OK;
}

}  // namespace android
