/**
* \file ServiceName.c
* \brief Common API for dealing with allowed service names.
* \author Dmytro Podgornyi (d.podgornyi@samsung.com)
* \version 0.1
* \date Created Oct 07, 2013
* \par In Samsung Ukraine R&D Center (SURC) under a contract between
* \par LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
* \par "Samsung Elecrtronics Co", Ltd (Seoul, Republic of Korea)
* \par Copyright: (c) Samsung Electronics Co, Ltd 2012. All rights reserved.
**/

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "commonConfig.h"
#include "PlatformConfig.h"
#include "ServiceName.h"
#include "log.h"

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

struct ServiceNameCtx
{
    const char name[MAX_SERVICE_NAME + 1];
    uint8_t TID[MAX_TID_SIZE];
    TaRotType_t type;    
};

static struct ServiceNameCtx serviceNameTbl[] =
{
    SERV_NAME_CTX_LIST,
};

#if (defined USE_QSEE)
#include "qsee_cfg_prop.h"
#define MAX_DISTNAME_PREFIX_SZ 120
#define MAX_TANAME_SZ 8
#define MAX_FULLNAME_SZ 128


#define ALT_ROT_DOMAIN_NAME "alt_rot_domain_name_dot"
#define DL_ROT_DOMAIN_NAME  "dl_rot_domain_name_dot"

//Qualcomm provided get_alt_rot_distname API.
static void get_alt_rot_distname(bool isDownloadableTa, char *i_appname, char *o_distname)
{
    const char *prop_name;
    uint32_t ret_size = 0;
    size_t len = 0;
    qsee_cfg_propvar_t *ptr = NULL;
    uint32_t prop[2 + (MAX_DISTNAME_PREFIX_SZ / sizeof(uint32_t))] = {0};
    char distname_prefix[MAX_DISTNAME_PREFIX_SZ] = {0};
    int i = 0;
    prop_name = isDownloadableTa? DL_ROT_DOMAIN_NAME : ALT_ROT_DOMAIN_NAME;
    if (QSEE_CFG_SUCCESS != qsee_cfg_getpropval(prop_name,
                                                    strlen(prop_name) + 1, 0,
                                                    (qsee_cfg_propvar_t *)&prop,
                                                    sizeof(prop), &ret_size)) {
        LOGE("'alt_rot_domain_name_dot' read failed, using legacy %s appname", (isDownloadableTa?"downloadable":"normal"));
        ret_size = snprintf(o_distname, MAX_TID_SIZE, "%s%s", (isDownloadableTa?(char*)ALTNAME:""), i_appname);
        return;
    }
    /*
    if (isDownloadableTa) {
        prop_name = DL_ROT_DOMAIN_NAME;

        if (QSEE_CFG_SUCCESS != qsee_cfg_getpropval(prop_name,
                                                    strlen(prop_name) + 1, 0,
                                                    (qsee_cfg_propvar_t *)&prop,
                                                    sizeof(prop), &ret_size)) {
            LOGE("'alt_rot_domain_name_dot' read failed, using legacy downloadable appname");
            ret_size = snprintf(o_distname, MAX_TID_SIZE, "%s%s", (char*)ALTNAME, i_appname);
            return;
        }
    } else {
        prop_name = ALT_ROT_DOMAIN_NAME;

        if (QSEE_CFG_SUCCESS != qsee_cfg_getpropval(prop_name,
                                                    strlen(prop_name) + 1, 0,
                                                    (qsee_cfg_propvar_t *)&prop,
                                                    sizeof(prop), &ret_size)) {
            LOGE("'alt_rot_domain_name_dot' read failed, using legacy appname");
            ret_size = strlcpy(o_distname, i_appname, MAX_TANAME_SZ);
            return;
        }
    }
    */
    ptr = (qsee_cfg_propvar_t *)prop;

    /* len = ret_size - sizeof(qsee_cfg_propvar_t) + padding */
    len = ret_size - sizeof(*ptr) + 2 * sizeof(ptr->val) + 1;

    if (len >= sizeof(distname_prefix)) {
        LOGE("'alt_rot_domain_name_dot' len invalid, using legacy appname");
        strlcpy(o_distname, i_appname, MAX_TANAME_SZ);
        return;
    }

    /* remove the quotes only when read from devcfg */
    memcpy(distname_prefix, &ptr->val[1], len - 1);
    distname_prefix[len] = '\0';

    /* finalize fully qualified distname */
    snprintf(o_distname,MAX_FULLNAME_SZ,"%s%s", distname_prefix,i_appname);
}

static int32_t getAltTaName(int32_t serviceIndex, char *taName)
{
    
    LOGI("%s start... - check Type : %d ", __func__ , serviceNameTbl[serviceIndex].type);
    switch (serviceNameTbl[serviceIndex].type) {
        case NORMAL_TA :
            get_alt_rot_distname(false, (char *)serviceNameTbl[serviceIndex].TID, taName);
            break;
        case DOWNLOADABLE_TA :
            get_alt_rot_distname(true, (char *)serviceNameTbl[serviceIndex].TID, taName);
            break;
        case SECUREBOOTKEY_TA :
            memcpy(taName, (char *)serviceNameTbl[serviceIndex].TID, sizeof(serviceNameTbl[serviceIndex].TID));
            break;
        default :
            LOGE("Unsupported Ta type : %d", serviceNameTbl[serviceIndex].type);
            return ERR_INVALID_ARGUMENT;
    }

    return NOT_ERROR;
}
#endif //End of USE_QSEE

static int32_t getServiceIndex(const char *serviceName)
{
    size_t serviceIndex = 0;

    for(serviceIndex = 0; serviceIndex < ARRAY_SIZE(serviceNameTbl); serviceIndex++)
    {
        if(strncmp(serviceName, (char *)serviceNameTbl[serviceIndex].name,
                    (strlen(serviceName) < strlen(serviceNameTbl[serviceIndex].name) ?
                     strlen(serviceName): strlen(serviceNameTbl[serviceIndex].name))) == 0)
            return serviceIndex;
    }

    return ERR_INVALID_ARGUMENT;
}

int isServiceNameRegistered(const char *serviceName)
{
    if(serviceName == NULL)
    {
        LOGE("%s : Invalid arguments.", __func__);
        return false;
    }

    if(getServiceIndex(serviceName) >= 0)
        return true;
    else
        return false;
}

int getTidByServiceName(const char* serviceName, char *TID, uint32_t *TIDLen)
{
    int32_t serviceIndex = 0;

    if(serviceName == NULL || TID == NULL || TIDLen == NULL)
    {
        LOGE("%s : Invalid arguments.", __func__);
        return ERR_INVALID_ARGUMENT;
    }

    if((serviceIndex = getServiceIndex(serviceName)) < 0)
    {
        LOGE("Failed to get index of %s with error %d.", serviceName, serviceIndex);
        return serviceIndex;
    }
    
#if (defined USE_QSEE)
    int32_t ret = NOT_ERROR;

    if ((ret = getAltTaName(serviceIndex, TID)) != 0) {
       LOGE("Failed to get altname with error %d", ret); 
       return ret;
    }

    *TIDLen = strlen((char *)serviceNameTbl[serviceIndex].TID);
#else
    *TIDLen = MAX_TID_SIZE;
    memcpy(TID, (char *)serviceNameTbl[serviceIndex].TID, *TIDLen);
#endif  // End of USE_QSEE

    LOGE("getTidByServiceName - TID : %s", TID);

    LOGD("%s is registered.", (char *)serviceNameTbl[serviceIndex].name);

    return NOT_ERROR;
}
