/*
 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 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_TAG "audio_hw_acdb"
//#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0

#include <stdlib.h>
#include <dlfcn.h>
#include <log/log.h>
#include <cutils/list.h>
#include <time.h>
#include "acdb.h"
#include "platform_api.h"

#ifdef INSTANCE_ID_ENABLED
int check_and_set_instance_id_support(struct mixer* mixer, bool acdb_support)
{
    const char *mixer_ctl_name = "Instance ID Support";
    struct mixer_ctl* ctl;

    ALOGV("%s", __func__);

    /* Check for ACDB and property instance ID support and issue mixer control */
    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
    if (!ctl) {
        ALOGE("%s: Could not get ctl for mixer cmd - %s",
                               __func__, mixer_ctl_name);
        return -EINVAL;
    }

    ALOGD("%s: Final Instance ID support:%d\n", __func__, acdb_support);
    if (mixer_ctl_set_value(ctl, 0, acdb_support) < 0) {
        ALOGE("%s: Could not set Instance ID support %d", __func__,
              acdb_support);
        return -EINVAL;
    }
    return 0;
}
#else
#define check_and_set_instance_id_support(x, y) -ENOSYS
#endif

int acdb_init(int snd_card_num)
{

    int result = -1;
    struct mixer *mixer = NULL;

    if(snd_card_num < 0) {
        ALOGE("invalid sound card number");
        return result;
    }

    mixer = mixer_open(snd_card_num);
    if (!mixer) {
        ALOGE("%s: Unable to open the mixer card: %d", __func__,
               snd_card_num);
        return result;
    }
    result = acdb_init_v2(mixer);
    mixer_close(mixer);
    return result;
}

int acdb_init_v2(struct mixer *mixer)
{

    int result = -1;
    char *cvd_version = NULL;

    const char *snd_card_name = NULL;
    struct acdb_platform_data *my_data = NULL;

    if (!mixer) {
       ALOGE("Invalid mixer handle");
       return result;
    }

    my_data = calloc(1, sizeof(struct acdb_platform_data));
    if (!my_data) {
        ALOGE("failed to allocate acdb platform data");
        goto cleanup;
    }

    list_init(&my_data->acdb_meta_key_list);

    /* Extract META KEY LIST INFO */
    platform_info_init(PLATFORM_INFO_XML_PATH, my_data, ACDB_EXTN);

    my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
    if (my_data->acdb_handle == NULL) {
        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
        goto cleanup;
    }

    ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);

    my_data->acdb_init_v4 = (acdb_init_v4_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_init_v4");
    if (my_data->acdb_init_v4 == NULL)
        ALOGE("%s: dlsym error %s for acdb_loader_init_v4", __func__, dlerror());

    my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_init_v3");
    if (my_data->acdb_init_v3 == NULL)
        ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());

    my_data->acdb_init_v2 = (acdb_init_v2_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_init_v2");
    if (my_data->acdb_init_v2 == NULL)
        ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());

    my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
                                                 "acdb_loader_init_ACDB");
    if (my_data->acdb_init == NULL && my_data->acdb_init_v2 == NULL
        && my_data->acdb_init_v3 == NULL && my_data->acdb_init_v4 == NULL) {
        ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
        goto cleanup;
    }

    /* Get CVD version */
    cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
    if (!cvd_version) {
        ALOGE("%s: Failed to allocate cvd version", __func__);
        goto cleanup;
    } else {
        struct mixer_ctl *ctl = NULL;
        int count = 0;

        ctl = mixer_get_ctl_by_name(mixer, CVD_VERSION_MIXER_CTL);
        if (!ctl) {
            ALOGE("%s: Could not get ctl for mixer cmd - %s",  __func__, CVD_VERSION_MIXER_CTL);
            goto cleanup;
        }
        mixer_ctl_update(ctl);

        count = mixer_ctl_get_num_values(ctl);
        if (count > MAX_CVD_VERSION_STRING_SIZE)
            count = MAX_CVD_VERSION_STRING_SIZE;

        result = mixer_ctl_get_array(ctl, cvd_version, count);
        if (result != 0) {
            ALOGE("%s: ERROR! mixer_ctl_get_array() failed to get CVD Version", __func__);
            goto cleanup;
        }
    }

    /* Get Sound card name */
    snd_card_name = mixer_get_name(mixer);
    if (!snd_card_name) {
        ALOGE("failed to allocate memory for snd_card_name");
        result = -1;
        goto cleanup;
    }

    snd_card_name = platform_get_snd_card_name_for_acdb_loader(snd_card_name);
    int key = 0;
    struct listnode *node = NULL;
    struct meta_key_list *key_info = NULL;
    static bool acdb_instance_id_support = false;

    my_data->acdb_init_data.cvd_version = cvd_version;
    my_data->acdb_init_data.snd_card_name = strdup(snd_card_name);
    my_data->acdb_init_data.meta_key_list = &my_data->acdb_meta_key_list;
    my_data->acdb_init_data.is_instance_id_supported = &acdb_instance_id_support;

    if (my_data->acdb_init_v4) {
        result = my_data->acdb_init_v4(&my_data->acdb_init_data, ACDB_LOADER_INIT_V4);
    } else if (my_data->acdb_init_v3) {
        result = my_data->acdb_init_v3(snd_card_name, cvd_version,
                                       &my_data->acdb_meta_key_list);
    } else if (my_data->acdb_init_v2) {
        node = list_head(&my_data->acdb_meta_key_list);
        key_info = node_to_item(node, struct meta_key_list, list);
        key = key_info->cal_info.nKey;
        result = my_data->acdb_init_v2(snd_card_name, cvd_version, key);
    } else {
        result = my_data->acdb_init();
    }
    ALOGD("%s: ACDB Instance ID support after ACDB init:%d\n",
          __func__, acdb_instance_id_support);
    check_and_set_instance_id_support(mixer, acdb_instance_id_support);

cleanup:
    if (NULL != my_data) {
        if (my_data->acdb_handle)
            dlclose(my_data->acdb_handle);

        struct listnode *node = NULL;
        struct meta_key_list *key_info = NULL;
        struct listnode *tempnode = NULL;
        list_for_each_safe(node, tempnode, &my_data->acdb_meta_key_list) {
            key_info = node_to_item(node, struct meta_key_list, list);
            list_remove(node);
            free(key_info);
        }
        free(my_data);
    }

    if (cvd_version)
        free(cvd_version);

    return result;
}

int acdb_set_metainfo_key(void *platform, char *name, int key) {

    struct meta_key_list *key_info = (struct meta_key_list *)
                                        calloc(1, sizeof(struct meta_key_list));
    struct acdb_platform_data *pdata = (struct acdb_platform_data *)platform;
    if (!key_info) {
        ALOGE("%s: Could not allocate memory for key %d", __func__, key);
        return -ENOMEM;
    }

    key_info->cal_info.nKey = key;
    strlcpy(key_info->name, name, sizeof(key_info->name));
    list_add_tail(&pdata->acdb_meta_key_list, &key_info->list);

    ALOGD("%s: successfully added module %s and key %d to the list", __func__,
               key_info->name, key_info->cal_info.nKey);

    return 0;
}
