/*
 * Copyright (C) 2018 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.
 */

#include "android_media_MicrophoneInfo.h"
#include "android_media_AudioErrors.h"
#include "core_jni_helpers.h"

using namespace android;

static jclass gArrayListClass;
static jmethodID gArrayListCstor;
static struct {
    jmethodID add;
} gArrayListMethods;

static jclass gFloatClass;
static jmethodID gFloatCstor;

static jclass gFloatArrayClass;

static jclass gIntegerClass;
static jmethodID gIntegerCstor;

static jclass gMicrophoneInfoClass;
static jmethodID gMicrophoneInfoCstor;

static jclass gMicrophoneInfoCoordinateClass;
static jmethodID gMicrophoneInfoCoordinateCstor;

static jclass gPairClass;
static jmethodID gPairCstor;

namespace android {

jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
        const media::MicrophoneInfo *microphoneInfo)
{
    jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
    jstring jDeviceId = NULL;
    jstring jAddress = NULL;
    jobject jGeometricLocation = NULL;
    jobject jOrientation = NULL;
    jobject jFrequencyResponses = NULL;
    jobject jChannelMappings = NULL;

    jDeviceId = env->NewStringUTF(String8(microphoneInfo->getDeviceId()).string());
    jAddress = env->NewStringUTF(String8(microphoneInfo->getAddress()).string());
    if (microphoneInfo->getGeometricLocation().size() != 3 ||
            microphoneInfo->getOrientation().size() != 3) {
        jStatus = nativeToJavaStatus(BAD_VALUE);
        goto exit;
    }
    jGeometricLocation = env->NewObject(gMicrophoneInfoCoordinateClass,
                                        gMicrophoneInfoCoordinateCstor,
                                        microphoneInfo->getGeometricLocation()[0],
                                        microphoneInfo->getGeometricLocation()[1],
                                        microphoneInfo->getGeometricLocation()[2]);
    jOrientation = env->NewObject(gMicrophoneInfoCoordinateClass,
                                  gMicrophoneInfoCoordinateCstor,
                                  microphoneInfo->getOrientation()[0],
                                  microphoneInfo->getOrientation()[1],
                                  microphoneInfo->getOrientation()[2]);
    // Create a list of Pair for frequency response.
    if (microphoneInfo->getFrequencyResponses().size() != 2 ||
            microphoneInfo->getFrequencyResponses()[0].size() !=
                    microphoneInfo->getFrequencyResponses()[1].size()) {
        jStatus = nativeToJavaStatus(BAD_VALUE);
        goto exit;
    }
    jFrequencyResponses = env->NewObject(gArrayListClass, gArrayListCstor);
    for (size_t i = 0; i < microphoneInfo->getFrequencyResponses()[0].size(); i++) {
        jobject jFrequency = env->NewObject(gFloatClass, gFloatCstor,
                                            microphoneInfo->getFrequencyResponses()[0][i]);
        jobject jResponse = env->NewObject(gFloatClass, gFloatCstor,
                                          microphoneInfo->getFrequencyResponses()[1][i]);
        jobject jFrequencyResponse = env->NewObject(gPairClass, gPairCstor, jFrequency, jResponse);
        env->CallBooleanMethod(jFrequencyResponses, gArrayListMethods.add, jFrequencyResponse);
        env->DeleteLocalRef(jFrequency);
        env->DeleteLocalRef(jResponse);
        env->DeleteLocalRef(jFrequencyResponse);
    }
    // Create a list of Pair for channel mapping.
    if (microphoneInfo->getChannelMapping().size() != AUDIO_CHANNEL_COUNT_MAX) {
        jStatus = nativeToJavaStatus(BAD_VALUE);
        goto exit;
    }
    jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor);
    for (size_t i = 0; i < microphoneInfo->getChannelMapping().size(); i++) {
        int channelMappingType = microphoneInfo->getChannelMapping()[i];
        if (channelMappingType != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
            jobject jChannelIndex = env->NewObject(gIntegerClass, gIntegerCstor, i);
            jobject jChannelMappingType = env->NewObject(gIntegerClass, gIntegerCstor,
                                                         channelMappingType);
            jobject jChannelMapping = env->NewObject(gPairClass, gPairCstor,
                                                     jChannelIndex, jChannelMappingType);
            env->CallBooleanMethod(jChannelMappings, gArrayListMethods.add, jChannelMapping);
            env->DeleteLocalRef(jChannelIndex);
            env->DeleteLocalRef(jChannelMappingType);
            env->DeleteLocalRef(jChannelMapping);
        }
    }
    *jMicrophoneInfo = env->NewObject(gMicrophoneInfoClass, gMicrophoneInfoCstor, jDeviceId,
                                      microphoneInfo->getType(), jAddress,
                                      microphoneInfo->getDeviceLocation(),
                                      microphoneInfo->getDeviceGroup(),
                                      microphoneInfo->getIndexInTheGroup(),
                                      jGeometricLocation, jOrientation,
                                      jFrequencyResponses, jChannelMappings,
                                      microphoneInfo->getSensitivity(),
                                      microphoneInfo->getMaxSpl(),
                                      microphoneInfo->getMinSpl(),
                                      microphoneInfo->getDirectionality());

exit:
    if (jDeviceId != NULL) {
        env->DeleteLocalRef(jDeviceId);
    }
    if (jAddress != NULL) {
        env->DeleteLocalRef(jAddress);
    }
    if (jFrequencyResponses != NULL) {
        env->DeleteLocalRef(jFrequencyResponses);
    }
    if (jChannelMappings != NULL) {
        env->DeleteLocalRef(jChannelMappings);
    }
    if (jGeometricLocation != NULL) {
        env->DeleteLocalRef(jGeometricLocation);
    }
    if (jOrientation != NULL) {
        env->DeleteLocalRef(jOrientation);
    }
    return jStatus;
}

}

int register_android_media_MicrophoneInfo(JNIEnv *env)
{
    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
    gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V");
    gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");

    jclass floatClass = FindClassOrDie(env, "java/lang/Float");
    gFloatClass = MakeGlobalRefOrDie(env, floatClass);
    gFloatCstor = GetMethodIDOrDie(env, floatClass, "<init>", "(F)V");

    jclass floatArrayClass = FindClassOrDie(env, "[F");
    gFloatArrayClass = MakeGlobalRefOrDie(env, floatArrayClass);

    jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
    gIntegerClass = MakeGlobalRefOrDie(env, integerClass);
    gIntegerCstor = GetMethodIDOrDie(env, integerClass, "<init>", "(I)V");

    jclass microphoneInfoClass = FindClassOrDie(env, "android/media/MicrophoneInfo");
    gMicrophoneInfoClass = MakeGlobalRefOrDie(env, microphoneInfoClass);
    gMicrophoneInfoCstor = GetMethodIDOrDie(env, microphoneInfoClass, "<init>",
            "(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V");

    jclass microphoneInfoCoordinateClass = FindClassOrDie(
            env, "android/media/MicrophoneInfo$Coordinate3F");
    gMicrophoneInfoCoordinateClass = MakeGlobalRefOrDie(env, microphoneInfoCoordinateClass);
    gMicrophoneInfoCoordinateCstor = GetMethodIDOrDie(env, microphoneInfoCoordinateClass, "<init>",
           "(FFF)V");

    jclass pairClass = FindClassOrDie(env, "android/util/Pair");
    gPairClass = MakeGlobalRefOrDie(env, pairClass);
    gPairCstor = GetMethodIDOrDie(env, pairClass, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");

    return 0;
}
