/**
 * Created: tianfang.shi@samsung.com
 * Data:    17-7-10
 */
/*#include <qsee_timer.h>*/
/*#include <bits/limits.h>*/

#include "tzWrappers/TzwCommon.h"
#include "tzWrappers/TzwString.h"
#include "tzWrappers/TzwAuth.h"
#include "tzWrappers/TzwSerialNumber.h"

#include "ta_logger.h"

#include "gp_oem.h"
#include "ifaa_fingerprint_id_table.h"
#include "ifaa_mem_utils.h"
#include "stdio.h"
/*#include "biometric_result.h"*/
/*#include "biometric_interrupt.h"*/
#include "string.h"

#define UNIQUE_ID_SIZE    (4 + 4 + 32)

TEE_Result TEE_GetDeviceId(void *deviceID, size_t *size) {
    LOG_D("DeviceID size (%uB):", *size);
    if(*size < UNIQUE_ID_SIZE){
        LOG_E("deviceID is too small to hold device id info");
        return IFAA_ERR_BUF_TOO_SHORT;
    }

    uint8_t uniqueId[UNIQUE_ID_SIZE] = {0,};
    uint8_t *pUuniq = uniqueId;
    const uint32_t siliconProviderCode = 15;
    // 1.bytes 0-3: Identify each silicon provider id, defined by SRC-T
    tzwMemMove(pUuniq, &siliconProviderCode, sizeof(siliconProviderCode));
    pUuniq += sizeof(siliconProviderCode);

#ifdef __CHIPSET__
    uint8_t chipId[4] = {'0', '0', '0', '0'};
    char *chipsetName = __CHIPSET__;
    uint8_t len = strlen(chipsetName);

    LOG_D("chipset name : %s", chipsetName);
    for(int i = len - 4, j = 0; j < 4; j++){
        chipId[j] = chipsetName[i + j];
    }
#else
    LOG_D("Not defined chip name,Please defined it on SConscript like msm8998");
    uint8_t chipId[4] = {'0', '0', '0', '0'};
#endif

    logByteArrayHex(chipId, 4, "+CHIPID+");

    // 2.bytes 4-7: SoC model ID
    tzwMemMove(pUuniq, chipId, sizeof(chipId));
    pUuniq += sizeof(chipId);

    TzwSerialNumber_t realSerial;
    TEE_Result status = tzwReadSerialNumber(&realSerial);
    if( TEE_SUCCESS != status){
        LOG_E("tzwReadSerialNumber error, 0x%08x", status);
        return status;
    }

    //3. bytes 8-40: TA-UUID(16B) * 2;
    size_t bytesLeft = (UNIQUE_ID_SIZE - 8) / 2;
    size_t min = bytesLeft > realSerial.size ? realSerial.size : bytesLeft;
    /*LOG_D("printable string num(default: 16): %d", min);*/
    for(size_t i = 0; i < min; i++){
        sprintf((char*)(pUuniq + 2 * i), "%02x", realSerial.serial[i]);
    }

    tzwMemMove(deviceID, uniqueId, *size);

    logByteArrayHex(deviceID, *size, "device ID");

    return TEE_SUCCESS;
}

TEE_Result TEE_AuthenticatorSignDigest(void *digest, size_t digestLen,
                                       void *signature,
                                       size_t *signatureLen) {
    S_VAR_NOT_USED(digest);
    S_VAR_NOT_USED(digestLen);
    S_VAR_NOT_USED(signature);
    S_VAR_NOT_USED(signatureLen);

    return TEE_ERROR_NOT_IMPLEMENTED;
}

int32_t TEE_GetAuthenticatorVersion(void) {

    return 2;
}

TEE_Result TEE_GetFpLastIdentifiedResult(int32_t *fid) {
    TEE_Result result = TEE_SUCCESS;

    uint8_t realFid[MAX_BIO_EXT_DATA_SIZE] = {0};
    uint32_t realFidBufferSize = MAX_BIO_EXT_DATA_SIZE;
    uint32_t fpIndex = 0;
    uint64_t challenge = 0;

    result = getLatestAuthResult(realFid, &realFidBufferSize, &fpIndex, &challenge);

    if(result == TEE_SUCCESS){
#ifdef __DEV_DEBUG__
        LOG_I("last real fid = %s", realFid);
#endif
        *fid = (int32_t) auto_get_ifaa_fid(FID_TABLE_PATH, FID_TABLE_PATH_LEN, realFid, fpIndex);
    }else{
        *fid = -1;
        LOG_I("getLatestAuthResult failed, status=0x%08x", result);
        /*LOG_I("getLatestAuthResult failed, status=%"PRIu32"", result);*/
        return TEE_ERROR_ACCESS_DENIED;
    }

    return result;
}

TEE_Result getEnrolledFingerPrint(SystemFidStruct *pEnrolledArray, uint8_t *realFidCnt) {

    LOG_FUNC_BEGIN;
    TA_ASSERT(pEnrolledArray != NULL);
    TA_ASSERT(realFidCnt != NULL);
   
    if(load_system_fid_table(pEnrolledArray, realFidCnt) != IFAA_ERR_SUCCESS) {
        LOG_E("load system table failed!");
        return TEE_ERROR_ACCESS_DENIED;
    }
    return TEE_SUCCESS;
}

TEE_Result TEE_GetFpList(uint8_t *idList, uint32_t *idListLen) {

    LOG_FUNC_BEGIN;
    TEE_Result result = TEE_SUCCESS;
    SystemFidStruct  enrolledFps[FID_TABLE_MAX] = {0};
    uint8_t realFidCnt = 0;

    result = getEnrolledFingerPrint(enrolledFps, &realFidCnt);
   
    LOG_D("getEnrolledFp result = 0x%08x, cnt = %d", result, realFidCnt);

    if(result == TEE_SUCCESS && realFidCnt > 0) {
        
        uint32_t ifaaIds[FID_TABLE_MAX] = {0};

        if(update_ifaa_fid(enrolledFps, ifaaIds, realFidCnt) == IFAA_ERR_SUCCESS) {
            *idListLen = realFidCnt*2*sizeof(uint32_t);
           uint8_t *pBuf = idList;
           for(uint32_t i = 0; i<realFidCnt; i++) {
                write32(pBuf, sizeof(uint32_t));
                pBuf += sizeof(uint32_t);
                write32(pBuf, ifaaIds[i]);
                pBuf += sizeof(uint32_t);
           }
        } else {
            LOG_E("TEE_GetFpList failed!");
            return TEE_ERROR_ACCESS_DENIED;   
        }

    } else {
        LOG_D("TEE_GetFpList failed, status = 0x%08x", result);
    }
    LOG_FUNC_END;
    return result;
}
