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

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/IMediaCodecList.h>
#include <media/MediaCodecInfo.h>

#include <utils/Vector.h>

#include <vector>

#include "android_runtime/AndroidRuntime.h"
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_media_Streams.h"

using namespace android;

/**
 * This object unwraps codec aliases into individual codec infos as the Java interface handles
 * aliases in this way.
 */
class JavaMediaCodecListWrapper {
public:
    struct Info {
        sp<MediaCodecInfo> info;
        AString alias;
    };

    const Info getCodecInfo(size_t index) const {
        if (index < mInfoList.size()) {
            return mInfoList[index];
        }
        // return
        return Info { nullptr /* info */, "(none)" /* alias */ };
    }

    size_t countCodecs() const {
        return mInfoList.size();
    }

    sp<IMediaCodecList> getCodecList() const {
        return mCodecList;
    }

    size_t findCodecByName(AString name) const {
        auto it = mInfoIndex.find(name);
        return it == mInfoIndex.end() ? -ENOENT : it->second;
    }

    JavaMediaCodecListWrapper(sp<IMediaCodecList> mcl)
            : mCodecList(mcl) {
        size_t numCodecs = mcl->countCodecs();
        for (size_t ix = 0; ix < numCodecs; ++ix) {
            sp<MediaCodecInfo> info = mcl->getCodecInfo(ix);
            Vector<AString> namesAndAliases;
            info->getAliases(&namesAndAliases);
            namesAndAliases.insertAt(0);
            namesAndAliases.editItemAt(0) = info->getCodecName();
            for (const AString &nameOrAlias : namesAndAliases) {
                if (mInfoIndex.count(nameOrAlias) > 0) {
                    // skip duplicate names or aliases
                    continue;
                }
                mInfoIndex.emplace(nameOrAlias, mInfoList.size());
                mInfoList.emplace_back(Info { info, nameOrAlias });
            }
        }
    }

private:
    sp<IMediaCodecList> mCodecList;
    std::vector<Info> mInfoList;
    std::map<AString, size_t> mInfoIndex;
};

static std::mutex sMutex;
static std::unique_ptr<JavaMediaCodecListWrapper> sListWrapper;

static const JavaMediaCodecListWrapper *getCodecList(JNIEnv *env) {
    std::lock_guard<std::mutex> lock(sMutex);
    if (sListWrapper == nullptr) {
        sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
        if (mcl == NULL) {
            // This should never happen unless something is really wrong
            jniThrowException(
                        env, "java/lang/RuntimeException", "cannot get MediaCodecList");
        }

        sListWrapper.reset(new JavaMediaCodecListWrapper(mcl));
    }
    return sListWrapper.get();
}

static JavaMediaCodecListWrapper::Info getCodecInfo(JNIEnv *env, jint index) {
    const JavaMediaCodecListWrapper *mcl = getCodecList(env);
    if (mcl == nullptr) {
        // Runtime exception already pending.
        return JavaMediaCodecListWrapper::Info { nullptr /* info */, "(none)" /* alias */ };
    }

    JavaMediaCodecListWrapper::Info info = mcl->getCodecInfo(index);
    if (info.info == NULL) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    }

    return info;
}

static jint android_media_MediaCodecList_getCodecCount(
        JNIEnv *env, jobject /* thiz */) {
    const JavaMediaCodecListWrapper *mcl = getCodecList(env);
    if (mcl == NULL) {
        // Runtime exception already pending.
        return 0;
    }

    return mcl->countCodecs();
}

static jstring android_media_MediaCodecList_getCodecName(
        JNIEnv *env, jobject /* thiz */, jint index) {
    JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index);
    if (info.info == NULL) {
        // Runtime exception already pending.
        return NULL;
    }

    const char *name = info.alias.c_str();
    return env->NewStringUTF(name);
}

static jstring android_media_MediaCodecList_getCanonicalName(
        JNIEnv *env, jobject /* thiz */, jint index) {
    JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index);
    if (info.info == NULL) {
        // Runtime exception already pending.
        return NULL;
    }

    const char *name = info.info->getCodecName();
    return env->NewStringUTF(name);
}

static jint android_media_MediaCodecList_findCodecByName(
        JNIEnv *env, jobject /* thiz */, jstring name) {
    if (name == NULL) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return -ENOENT;
    }

    const char *nameStr = env->GetStringUTFChars(name, NULL);
    if (nameStr == NULL) {
        // Out of memory exception already pending.
        return -ENOENT;
    }

    const JavaMediaCodecListWrapper *mcl = getCodecList(env);
    if (mcl == NULL) {
        // Runtime exception already pending.
        env->ReleaseStringUTFChars(name, nameStr);
        return -ENOENT;
    }

    jint ret = mcl->findCodecByName(nameStr);
    env->ReleaseStringUTFChars(name, nameStr);
    return ret;
}

static jboolean android_media_MediaCodecList_getAttributes(
        JNIEnv *env, jobject /* thiz */, jint index) {
    JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index);
    if (info.info == NULL) {
        // Runtime exception already pending.
        return 0;
    }

    return info.info->getAttributes();
}

static jarray android_media_MediaCodecList_getSupportedTypes(
        JNIEnv *env, jobject /* thiz */, jint index) {
    JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index);
    if (info.info == NULL) {
        // Runtime exception already pending.
        return NULL;
    }

    Vector<AString> types;
    info.info->getSupportedMediaTypes(&types);

    jclass clazz = env->FindClass("java/lang/String");
    CHECK(clazz != NULL);

    jobjectArray array = env->NewObjectArray(types.size(), clazz, NULL);

    for (size_t i = 0; i < types.size(); ++i) {
        jstring obj = env->NewStringUTF(types.itemAt(i).c_str());
        env->SetObjectArrayElement(array, i, obj);
        env->DeleteLocalRef(obj);
        obj = NULL;
    }

    return array;
}

static jobject android_media_MediaCodecList_getCodecCapabilities(
        JNIEnv *env, jobject /* thiz */, jint index, jstring type) {
    if (type == NULL) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return NULL;
    }

    JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index);
    if (info.info == NULL) {
        // Runtime exception already pending.
        return NULL;
    }


    const char *typeStr = env->GetStringUTFChars(type, NULL);
    if (typeStr == NULL) {
        // Out of memory exception already pending.
        return NULL;
    }

    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
    Vector<uint32_t> colorFormats;

    sp<AMessage> defaultFormat = new AMessage();
    defaultFormat->setString("mime", typeStr);

    // TODO query default-format also from codec/codec list
    const sp<MediaCodecInfo::Capabilities> &capabilities =
        info.info->getCapabilitiesFor(typeStr);
    env->ReleaseStringUTFChars(type, typeStr);
    typeStr = NULL;
    if (capabilities == NULL) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return NULL;
    }

    capabilities->getSupportedColorFormats(&colorFormats);
    capabilities->getSupportedProfileLevels(&profileLevels);
    sp<AMessage> details = capabilities->getDetails();
    bool isEncoder = info.info->isEncoder();

    jobject defaultFormatObj = NULL;
    if (ConvertMessageToMap(env, defaultFormat, &defaultFormatObj)) {
        return NULL;
    }

    jobject infoObj = NULL;
    if (ConvertMessageToMap(env, details, &infoObj)) {
        env->DeleteLocalRef(defaultFormatObj);
        return NULL;
    }

    jclass capsClazz =
        env->FindClass("android/media/MediaCodecInfo$CodecCapabilities");
    CHECK(capsClazz != NULL);

    jclass profileLevelClazz =
        env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel");
    CHECK(profileLevelClazz != NULL);

    jobjectArray profileLevelArray =
        env->NewObjectArray(profileLevels.size(), profileLevelClazz, NULL);

    jfieldID profileField =
        env->GetFieldID(profileLevelClazz, "profile", "I");

    jfieldID levelField =
        env->GetFieldID(profileLevelClazz, "level", "I");

    for (size_t i = 0; i < profileLevels.size(); ++i) {
        const MediaCodecInfo::ProfileLevel &src = profileLevels.itemAt(i);

        jobject profileLevelObj = env->AllocObject(profileLevelClazz);

        env->SetIntField(profileLevelObj, profileField, src.mProfile);
        env->SetIntField(profileLevelObj, levelField, src.mLevel);

        env->SetObjectArrayElement(profileLevelArray, i, profileLevelObj);

        env->DeleteLocalRef(profileLevelObj);
        profileLevelObj = NULL;
    }

    jintArray colorFormatsArray = env->NewIntArray(colorFormats.size());

    for (size_t i = 0; i < colorFormats.size(); ++i) {
        jint val = colorFormats.itemAt(i);
        env->SetIntArrayRegion(colorFormatsArray, i, 1, &val);
    }

    jmethodID capsConstructID = env->GetMethodID(capsClazz, "<init>",
            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZ"
            "Ljava/util/Map;Ljava/util/Map;)V");

    jobject caps = env->NewObject(capsClazz, capsConstructID,
            profileLevelArray, colorFormatsArray, isEncoder,
            defaultFormatObj, infoObj);

    env->DeleteLocalRef(profileLevelArray);
    profileLevelArray = NULL;

    env->DeleteLocalRef(colorFormatsArray);
    colorFormatsArray = NULL;

    env->DeleteLocalRef(defaultFormatObj);
    defaultFormatObj = NULL;

    env->DeleteLocalRef(infoObj);
    infoObj = NULL;

    return caps;
}

static jobject android_media_MediaCodecList_getGlobalSettings(JNIEnv *env, jobject /* thiz */) {
    const JavaMediaCodecListWrapper *mcl = getCodecList(env);
    if (mcl == NULL) {
        // Runtime exception already pending.
        return NULL;
    }

    const sp<AMessage> settings = mcl->getCodecList()->getGlobalSettings();
    if (settings == NULL) {
        jniThrowException(env, "java/lang/RuntimeException", "cannot get global settings");
        return NULL;
    }

    jobject settingsObj = NULL;
    if (ConvertMessageToMap(env, settings, &settingsObj)) {
        return NULL;
    }

    return settingsObj;
}

static void android_media_MediaCodecList_native_init(JNIEnv* /* env */) {
}

static const JNINativeMethod gMethods[] = {
    { "native_getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },

    { "getCanonicalName", "(I)Ljava/lang/String;",
      (void *)android_media_MediaCodecList_getCanonicalName },

    { "getCodecName", "(I)Ljava/lang/String;",
      (void *)android_media_MediaCodecList_getCodecName },

    { "getAttributes", "(I)I", (void *)android_media_MediaCodecList_getAttributes },

    { "getSupportedTypes", "(I)[Ljava/lang/String;",
      (void *)android_media_MediaCodecList_getSupportedTypes },

    { "getCodecCapabilities",
      "(ILjava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;",
      (void *)android_media_MediaCodecList_getCodecCapabilities },

    { "native_getGlobalSettings",
      "()Ljava/util/Map;",
      (void *)android_media_MediaCodecList_getGlobalSettings },

    { "findCodecByName", "(Ljava/lang/String;)I",
      (void *)android_media_MediaCodecList_findCodecByName },

    { "native_init", "()V", (void *)android_media_MediaCodecList_native_init },
};

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

