/*
 * Copyright 2015, 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 "JMediaDataSource-JNI"
#include <utils/Log.h>

#include "android_media_MediaDataSource.h"

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

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

namespace android {

JMediaDataSource::JMediaDataSource(JNIEnv* env, jobject source)
    : mJavaObjStatus(OK), mSizeIsCached(false), mCachedSize(0), mMemory(NULL) {
    mMediaDataSourceObj = env->NewGlobalRef(source);
    CHECK(mMediaDataSourceObj != NULL);

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

    mReadMethod = env->GetMethodID(mediaDataSourceClass.get(), "readAt", "(J[BII)I");
    CHECK(mReadMethod != NULL);
    mGetSizeMethod = env->GetMethodID(mediaDataSourceClass.get(), "getSize", "()J");
    CHECK(mGetSizeMethod != NULL);
    mCloseMethod = env->GetMethodID(mediaDataSourceClass.get(), "close", "()V");
    CHECK(mCloseMethod != NULL);

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

    sp<MemoryDealer> memoryDealer = new MemoryDealer(kBufferSize, "JMediaDataSource");
    mMemory = memoryDealer->allocate(kBufferSize);
    if (mMemory == NULL) {
        ALOGE("Failed to allocate memory!");
    }
}

JMediaDataSource::~JMediaDataSource() {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    env->DeleteGlobalRef(mMediaDataSourceObj);
    env->DeleteGlobalRef(mByteArrayObj);
}

sp<IMemory> JMediaDataSource::getIMemory() {
    Mutex::Autolock lock(mLock);
    return mMemory;
}

ssize_t JMediaDataSource::readAt(off64_t offset, size_t size) {
    Mutex::Autolock lock(mLock);

    if (mJavaObjStatus != OK || mMemory == NULL) {
        return -1;
    }
    if (size > kBufferSize) {
        size = kBufferSize;
    }

    JNIEnv* env = AndroidRuntime::getJNIEnv();
    jint numread = env->CallIntMethod(mMediaDataSourceObj, mReadMethod,
            (jlong)offset, mByteArrayObj, (jint)0, (jint)size);
    if (env->ExceptionCheck()) {
        ALOGW("An exception occurred in readAt()");
        LOGW_EX(env);
        env->ExceptionClear();
        mJavaObjStatus = UNKNOWN_ERROR;
        return -1;
    }
    if (numread < 0) {
        if (numread != -1) {
            ALOGW("An error occurred in readAt()");
            mJavaObjStatus = UNKNOWN_ERROR;
            return -1;
        } else {
            // numread == -1 indicates EOF
            return 0;
        }
    }
    if ((size_t)numread > size) {
        ALOGE("readAt read too many bytes.");
        mJavaObjStatus = UNKNOWN_ERROR;
        return -1;
    }

    ALOGV("readAt %lld / %zu => %d.", (long long)offset, size, numread);
    env->GetByteArrayRegion(mByteArrayObj, 0, numread, (jbyte*)mMemory->pointer());
    return numread;
}

status_t JMediaDataSource::getSize(off64_t* size) {
    Mutex::Autolock lock(mLock);

    if (mJavaObjStatus != OK) {
        return UNKNOWN_ERROR;
    }
    if (mSizeIsCached) {
        return mCachedSize;
    }

    JNIEnv* env = AndroidRuntime::getJNIEnv();
    *size = env->CallLongMethod(mMediaDataSourceObj, mGetSizeMethod);
    if (env->ExceptionCheck()) {
        ALOGW("An exception occurred in getSize()");
        LOGW_EX(env);
        env->ExceptionClear();
        // After returning an error, size shouldn't be used by callers.
        *size = UNKNOWN_ERROR;
        mJavaObjStatus = UNKNOWN_ERROR;
        return UNKNOWN_ERROR;
    }

    // The minimum size should be -1, which indicates unknown size.
    if (*size < 0) {
        *size = -1;
    }

    mCachedSize = *size;
    mSizeIsCached = true;
    return OK;
}

void JMediaDataSource::close() {
    Mutex::Autolock lock(mLock);

    JNIEnv* env = AndroidRuntime::getJNIEnv();
    env->CallVoidMethod(mMediaDataSourceObj, mCloseMethod);
    // The closed state is effectively the same as an error state.
    mJavaObjStatus = UNKNOWN_ERROR;
}

}  // namespace android
