/*
 * Copyright (C) 2015-2020 Intel Corporation
 *
 * 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 "AiqInitData"

#include <sys/stat.h>
#include <unordered_map>

#include "iutils/CameraLog.h"
#include "AiqInitData.h"
#include "AiqUtils.h"
#include "PlatformData.h"
#include "ia_types.h"

using std::string;

namespace icamera {

AiqdData::AiqdData(TuningMode tuningMode, const string& sensorName) :
    mDataPtr(nullptr)
{
    CLEAR(mBinaryData);

    mAiqdFileName.append(CAMERA_CACHE_DIR);
    mAiqdFileName.append(sensorName);
    mAiqdFileName.append("_");
    mAiqdFileName.append(CameraUtils::tuningMode2String(tuningMode));
    mAiqdFileName.append(".aiqd");

    LOG1("%s, aiqd file name %s", __func__, mAiqdFileName.c_str());
    loadAiqdFromFile();
};

AiqdData::~AiqdData()
{
    LOG1("%s, aiqd file name %s", __func__, mAiqdFileName.c_str());
}

ia_binary_data* AiqdData::getAiqd()
{
    return mDataPtr ? &mBinaryData : nullptr;
}

void AiqdData::saveAiqd(const ia_binary_data& data)
{
    LOG1("%s", __func__);

    if (!mDataPtr || data.size != mBinaryData.size) {
        mDataPtr.reset(new char[data.size]);
        mBinaryData.size = data.size;
        mBinaryData.data = mDataPtr.get();
    }
    MEMCPY_S(mBinaryData.data, mBinaryData.size, data.data, data.size);

    saveAiqdToFile();
}

void AiqdData::loadAiqdFromFile()
{
    LOG1("%s", __func__);

    // Get file size
    struct stat fileStat;
    CLEAR(fileStat);
    int ret = stat(mAiqdFileName.c_str(), &fileStat);
    if (ret != 0) {
        LOG1("There is no aiqd file %s", mAiqdFileName.c_str());
        return;
    }

    // Opem aiqd file
    FILE* fp = fopen(mAiqdFileName.c_str(), "rb");
    CheckWarning(fp == nullptr, VOID_VALUE, "Failed to open aiqd file %s, error %s",
                 mAiqdFileName.c_str(), strerror(errno));

    std::unique_ptr<char[]> dataPtr(new char[fileStat.st_size]);

    // Read aiqd data
    size_t readSize = fread(dataPtr.get(), sizeof(char), fileStat.st_size, fp);
    fclose(fp);

    CheckWarning(readSize != (size_t)fileStat.st_size, VOID_VALUE,
                 "Failed to read aiqd %s, error %s",
                 mAiqdFileName.c_str(), strerror(errno));

    mDataPtr = move(dataPtr);
    mBinaryData.data = mDataPtr.get();
    mBinaryData.size = fileStat.st_size;
    LOG1("%s, aiqd file %s, size %d", __func__, mAiqdFileName.c_str(), mBinaryData.size);
}

void AiqdData::saveAiqdToFile()
{
    LOG1("%s", __func__);

    // Open aiqd file
    FILE* fp = fopen(mAiqdFileName.c_str(), "wb");
    CheckWarning(fp == nullptr, VOID_VALUE, "Failed to open aiqd file %s, error %s",
                 mAiqdFileName.c_str(), strerror(errno));

    // Write aiqd data to file
    size_t writeSize = fwrite(mBinaryData.data, 1, mBinaryData.size, fp);
    if (writeSize != mBinaryData.size) {
        LOGW("Failed to write aiqd data %s, error %s", mAiqdFileName.c_str(), strerror(errno));
        fclose(fp);
        return;
    }

    fflush(fp);
    fclose(fp);

    LOG1("%s, aiqd file %s, size %d", __func__, mAiqdFileName.c_str(), mBinaryData.size);
}

CpfConf::CpfConf(ia_binary_data* nvmData) : mNvmData(nvmData)
{
    mLard = new IntelLard();
    mCmc = std::unique_ptr<IntelCmc>(new IntelCmc());
    CLEAR(mAiq);
    CLEAR(mIsp);
    CLEAR(mOthers);
}

CpfConf::~CpfConf()
{
    delete mLard;
    LOG1("@%s", __func__);
}

int CpfConf::init(const ia_binary_data& cpfData, const LardTagConfig* lardTagCfg)
{
    LOG1("@%s", __func__);

    CheckWarning(mCmc->getCmc(), OK, "cmc has already been init before!");
    CheckError((cpfData.data == nullptr), BAD_VALUE, "Error Initializing CPF configure");

    bool cmcRet = false;
    ia_lard *iaLard = mLard->init(&cpfData);
    if (iaLard) {
        LOG1("AIQB file supported by lard.");
        ia_lard_input_params lardInputParams;
        initLardInputParam(*iaLard, lardTagCfg, &lardInputParams);

        ia_lard_results* lardResults;
        // Run ia_lard, result is nullptr if aiqb file is not supported
        ia_err iaErr = mLard->run(iaLard, &lardInputParams, &lardResults);
        if (lardResults != nullptr) {
            LOG1("ia_lard_run success, using lard to get cmc mode and tuning.");
            cmcRet = mCmc->init(&lardResults->aiqb_cmc_data, mNvmData);
            mAiq = lardResults->aiqb_aiq_data;
            mIsp = lardResults->aiqb_isp_data;
            mOthers = lardResults->aiqb_other_data;
        } else {
            LOGE("Fail to run ia_lard, iaErr = %d", iaErr);
        }
        mLard->deinit(iaLard);
    } else {
        LOG1("Lard not supported. The AIQB file may be in old CPF format");
        cmcRet = mCmc->init(&cpfData, mNvmData);
        mAiq = cpfData;
        mIsp = cpfData;
        mOthers = cpfData;
    }
    CheckError(!cmcRet, FAILED_TRANSACTION, "Error cmc parser init!");

    return OK;
}

ia_cmc_t* CpfConf::getCmc() const
{
    return mCmc->getCmc();
}

uintptr_t CpfConf::getCmcHandle() const
{
    return mCmc->getCmcHandle();
}

void CpfConf::getIspData(ia_binary_data* ispData)
{
    ispData->data = mIsp.data;
    ispData->size = mIsp.size;
}

void CpfConf::getAiqData(ia_binary_data* aiqData)
{
    aiqData->data = mAiq.data;
    aiqData->size = mAiq.size;
}

void CpfConf::getOtherData(ia_binary_data* otherData)
{
    otherData->data = mOthers.data;
    otherData->size = mOthers.size;
}

void CpfConf::deinit()
{
    mCmc->deinit();
}

void CpfConf::initLardInputParam(const ia_lard& iaLard,
                                 const LardTagConfig* lardTagCfg,
                                 ia_lard_input_params* lardInputParam)
{
    if (!lardTagCfg) {
        lardInputParam->cmc_mode_tag = FOURCC_TO_UL('D','F','L','T');
        lardInputParam->aiq_mode_tag = FOURCC_TO_UL('D','F','L','T');
        lardInputParam->isp_mode_index = FOURCC_TO_UL('D','F','L','T');
        lardInputParam->others_mode_tag = FOURCC_TO_UL('D','F','L','T');
        return;
    }

    unsigned int count = 0;
    const unsigned int *tags = nullptr;

    mLard->getTagList(const_cast<ia_lard*>(&iaLard), FOURCC_TO_UL('L','C','M','C'), &count, &tags);
    lardInputParam->cmc_mode_tag = isTagValid(lardTagCfg->cmcTag, count, tags) ? \
                                   lardTagCfg->cmcTag : FOURCC_TO_UL('D','F','L','T');

    mLard->getTagList(const_cast<ia_lard*>(&iaLard), FOURCC_TO_UL('L','A','I','Q'), &count, &tags);
    lardInputParam->aiq_mode_tag = isTagValid(lardTagCfg->aiqTag, count, tags) ? \
                                   lardTagCfg->aiqTag : FOURCC_TO_UL('D','F','L','T');

    mLard->getTagList(const_cast<ia_lard*>(&iaLard), FOURCC_TO_UL('L','I','S','P'), &count, &tags);
    lardInputParam->isp_mode_index = isTagValid(lardTagCfg->ispTag, count, tags) ? \
                                     lardTagCfg->ispTag : FOURCC_TO_UL('D','F','L','T');

    mLard->getTagList(const_cast<ia_lard*>(&iaLard), FOURCC_TO_UL('L','T','H','R'), &count, &tags);
    lardInputParam->others_mode_tag = isTagValid(lardTagCfg->othersTag, count, tags) ? \
                                      lardTagCfg->othersTag : FOURCC_TO_UL('D','F','L','T');

    LOG1("@%s: The lard tags are: aiq-0x%x, isp-0x%x, cmc-0x%x, others-0x%x", __func__,
        lardInputParam->aiq_mode_tag, lardInputParam->isp_mode_index,
        lardInputParam->cmc_mode_tag, lardInputParam->others_mode_tag);
}

bool CpfConf::isTagValid(unsigned int tag, unsigned int count, const unsigned int* tags)
{
    if (tags != nullptr) {
        for (unsigned int i = 0; i < count; i++) {
            if (tags[i] == tag) return true;
        }
    }
    LOG1("@%s: Tag 0x%x is not valid. Will use DFLT instead.", __func__, tag);
    return false;
}

CpfStore::CpfStore(const std::string& sensorName, const std::string& camCfgDir,
                   const std::vector<TuningConfig>& tuningCfg,
                   const std::vector<LardTagConfig>& lardTagCfg,
                   const std::string& nvmPath,
                   std::unordered_map<std::string, std::string> camModuleToAiqbMap,
                   ia_binary_data* nvmData)
{
    LOG1("@%s:Sensor Name = %s", __func__, sensorName.c_str());

    LardTagConfig* oneLardTagCfg = nullptr;

    CLEAR(mCpfConfig);
    for (auto &cfg : tuningCfg) {
        if (mCpfConfig[cfg.tuningMode] != nullptr) {
            continue;
        }

        if (cfg.aiqbName.empty()) {
            LOGE("aiqb name is empty, sensor name %s", sensorName.c_str());
            continue;
        }

        std::string aiqbName(cfg.aiqbName);
        if (!camModuleToAiqbMap.empty()) {
            std::string cameraModule;
            int ret = getCameraModuleFromEEPROM(nvmPath, &cameraModule);
            if (ret == OK) {
                if (camModuleToAiqbMap.find(cameraModule) != camModuleToAiqbMap.end()) {
                    aiqbName.assign(camModuleToAiqbMap[cameraModule]);
                    LOG1("@%s, aiqb name %s", __func__, aiqbName.c_str());
                }
            }
        }

        if (mCpfData.find(aiqbName) == mCpfData.end()) {
            // Obtain the configurations
            if (loadConf(camCfgDir, aiqbName) != OK) {
                LOGE("load file %s failed, sensor %s", aiqbName.c_str(), sensorName.c_str());
                continue;
            }
        }

        oneLardTagCfg = nullptr;
        for (size_t i = 0; i < lardTagCfg.size(); i++) {
            if (cfg.tuningMode == lardTagCfg[i].tuningMode) {
                oneLardTagCfg = const_cast<LardTagConfig*>(&lardTagCfg[i]);
                break;
            }
        }

        CpfConf* cpfConf = new CpfConf(nvmData);

        cpfConf->init(mCpfData[aiqbName], oneLardTagCfg);
        mCpfConfig[cfg.tuningMode] = cpfConf;
    }
}

CpfStore::~CpfStore()
{
    LOG1("@%s", __func__);
    for (int mode=0; mode<TUNING_MODE_MAX; mode++) {
        if (mCpfConfig[mode]) {
            mCpfConfig[mode]->deinit();
            delete mCpfConfig[mode];
        }
    }
    for (auto &cpfData : mCpfData) {
        if (cpfData.second.data) {
            free(cpfData.second.data);
        }
    }
    mCpfData.clear();
}

int CpfStore::getCameraModuleFromEEPROM(const std::string& nvmPath, std::string* cameraModule)
{
    LOG1("@%s, nvmPath %s", __func__, nvmPath.c_str());

    CheckError(nvmPath.empty(), NAME_NOT_FOUND, "nvmPath is empty");

    const int moduleInfoSize = CAMERA_MODULE_INFO_SIZE;
    const int moduleInfoOffset = CAMERA_MODULE_INFO_OFFSET;
    struct CameraModuleInfo cameraModuleInfo;
    CLEAR(cameraModuleInfo);
    FILE* eepromFile = fopen(nvmPath.c_str(), "rb");
    CheckError(!eepromFile, UNKNOWN_ERROR, "Failed to open EEPROM file in %s", nvmPath.c_str());

    // file size should be larger than CAMERA_MODULE_INFO_OFFSET
    fseek(eepromFile, 0, SEEK_END);
    int nvmDataSize = static_cast<int>(ftell(eepromFile));
    if (nvmDataSize < moduleInfoOffset) {
        LOGE("EEPROM data is too small");
        fclose(eepromFile);
        return NOT_ENOUGH_DATA;
    }

    fseek(eepromFile, -1 * moduleInfoOffset, SEEK_END);
    int ret = fread(&cameraModuleInfo, moduleInfoSize, 1, eepromFile);
    fclose(eepromFile);
    CheckError(!ret, UNKNOWN_ERROR, "Failed to read module info %d", ret);

    char tmpName[CAMERA_MODULE_INFO_SIZE];
    snprintf(tmpName, CAMERA_MODULE_INFO_SIZE, "%c%c%x-%c%c-%d", cameraModuleInfo.mSensorVendor[0],
             cameraModuleInfo.mSensorVendor[1], cameraModuleInfo.mSensorModel,
             cameraModuleInfo.mModuleVendor[0], cameraModuleInfo.mModuleVendor[1],
             cameraModuleInfo.mModuleProduct);

    cameraModule->assign(tmpName);
    LOG1("%s, aiqb name %s", __func__, cameraModule->c_str());

    return OK;
}

/**
 * findConfigFile
 *
 * Search the path where CPF files are stored
*/
int CpfStore::findConfigFile(const std::string& camCfgDir, std::string* cpfPathName)
{
    LOG1("@%s, cpfPathName:%p", __func__, cpfPathName);
    CheckError(!cpfPathName, BAD_VALUE, "@%s, cpfPathName is nullptr", __func__);

    std::vector<string> configFilePath;
    configFilePath.push_back("./");
    configFilePath.push_back(camCfgDir);
    int configFileCount = configFilePath.size();

    string cpfFile;
    for (int i = 0; i < configFileCount; i++) {
        cpfFile.append(configFilePath.at(i));
        cpfFile.append(*cpfPathName);
        struct stat st;
        if (!stat(cpfFile.c_str(), &st))
            break;
        cpfFile.clear();
    }

    if (cpfFile.empty()) {//CPF file not found
        LOG1("@%s:No CPF file found for %s", __func__,cpfPathName->c_str());
        return NAME_NOT_FOUND;
    }

    *cpfPathName = cpfFile;
    LOG1("@%s:CPF file found %s", __func__,cpfPathName->c_str());
    return OK;
}

/**
 * loadConf
 *
 * load the CPF file
*/
int CpfStore::loadConf(const std::string& camCfgDir, const std::string& aiqbName)
{
    LOG1("@%s", __func__);
    int ret = OK;
    const char *suffix = ".aiqb";

    string cpfPathName = aiqbName;
    cpfPathName.append(suffix);
    LOG1("aiqb file name %s", cpfPathName.c_str());

    if (findConfigFile(camCfgDir, &cpfPathName) != OK) {
        LOGE("CpfStore no aiqb file:%s", aiqbName.c_str());
        return NAME_NOT_FOUND;
    }

    LOG1("Opening CPF file \"%s\"", cpfPathName.c_str());
    FILE *file = fopen(cpfPathName.c_str(), "rb");
    CheckError((file == nullptr), NAME_NOT_FOUND, "ERROR in opening CPF file \"%s\": %s!", cpfPathName.c_str(), strerror(errno));
    do {
        int fileSize;
        if ((fseek(file, 0, SEEK_END) < 0) || ((fileSize = ftell(file)) < 0) || (fseek(file, 0, SEEK_SET) < 0)) {
            LOGE("ERROR querying properties of CPF file \"%s\": %s!", cpfPathName.c_str(), strerror(errno));
            ret = BAD_VALUE;
            break;
        }

        mCpfData[aiqbName].data = malloc(fileSize);
        if (!mCpfData[aiqbName].data) {
            LOGE("ERROR no memory in %s!", __func__);
            ret = NO_MEMORY;
            break;
        }

        if (fread(mCpfData[aiqbName].data, fileSize, 1, file) < 1) {
            LOGE("ERROR reading CPF file \"%s\"!", cpfPathName.c_str());
            ret = INVALID_OPERATION;
            break;
        }
        mCpfData[aiqbName].size = fileSize;
    } while (0);

    if (fclose(file)) {
        LOGE("ERROR in closing CPF file \"%s\": %s!", cpfPathName.c_str(), strerror(errno));
    }

    return ret;
}

/**
 * convenience getter for Isp data, Aiq data, cmc data and other data.
 */
int CpfStore::getCpfAndCmc(ia_binary_data* ispData,
                           ia_binary_data* aiqData,
                           ia_binary_data* otherData,
                           uintptr_t* cmcHandle,
                           TuningMode mode,
                           ia_cmc_t** cmcData)
{
    LOG1("@%s mode = %d", __func__, mode);
    CheckError((mCpfConfig[mode] == nullptr), NO_INIT, "@%s, No aiqb init, mode = %d", __func__, mode);
    if (ispData != nullptr)
        mCpfConfig[mode]->getIspData(ispData);
    if (aiqData != nullptr)
        mCpfConfig[mode]->getAiqData(aiqData);
    if (otherData != nullptr)
        mCpfConfig[mode]->getOtherData(otherData);
    if (cmcData) {
        *cmcData = mCpfConfig[mode]->getCmc();
    }
    if (cmcHandle) {
        *cmcHandle = mCpfConfig[mode]->getCmcHandle();
    }

    if (mode == TUNING_MODE_VIDEO_ULL) {
        LOG2("@%s ULL mode, ULL cpf file is used", __func__);
    } else if (mode == TUNING_MODE_VIDEO_CUSTOM_AIC) {
        LOG2("@%s CUSTOM AIC mode, CUSTOM AIC cpf file is used", __func__);
    } else if (mode == TUNING_MODE_VIDEO_LL) {
        LOG2("@%s VIDEO LL mode, VIDEO LL cpf file is used", __func__);
    } else if (mode == TUNING_MODE_VIDEO_REAR_VIEW) {
        LOG2("@%s VIDEO Rear View mode, VIDEO REAR VIEW cpf file is used", __func__);
    } else if (mode == TUNING_MODE_VIDEO_HITCH_VIEW) {
        LOG2("@%s VIDEO Hitch View mode, VIDEO HITCH VIEW cpf file is used", __func__);
    } else {
        LOG2("@%s VIDEO mode, default cpf file is used", __func__);
    }

    return OK;
}

AiqInitData::AiqInitData(const std::string& sensorName,
                         const std::string& camCfgDir,
                         const std::vector<TuningConfig>& tuningCfg,
                         const std::vector<LardTagConfig>& lardTagCfg,
                         const std::string& nvmDir,
                         int maxNvmSize,
                         const std::unordered_map<std::string, std::string>& camModuleToAiqbMap) :
    mSensorName(sensorName),
    mCamCfgDir(camCfgDir),
    mMaxNvmSize(maxNvmSize),
    mTuningCfg(tuningCfg),
    mLardTagCfg(lardTagCfg),
    mCpfStore(nullptr),
    mCameraModuleToAiqbMap(camModuleToAiqbMap),
    mNvmDataBuf(nullptr),
    mMakerNote(nullptr)
{
    CLEAR(mNvmData);
    mMakerNote = std::unique_ptr<MakerNote>(new MakerNote);

    if (nvmDir.length() > 0) {
        mNvmPath.append(NVM_DATA_PATH);

        mNvmPath.append(nvmDir);
        if (mNvmPath.back() != '/')
            mNvmPath.append("/");

        mNvmPath.append("eeprom");
        LOG2("NVM data is located in %s", mNvmPath.c_str());
    }
}

AiqInitData::~AiqInitData()
{
    delete mCpfStore;
    for (auto aiqd : mAiqdDataMap) {
        delete aiqd.second;
    }
}

int AiqInitData::getCpfAndCmc(ia_binary_data* ispData,
                              ia_binary_data* aiqData,
                              ia_binary_data* otherData,
                              uintptr_t* cmcHandle,
                              TuningMode mode,
                              ia_cmc_t** cmcData)
{
    if (!mCpfStore) {
        ia_binary_data* nvmData = getNvm();
        mCpfStore = new CpfStore(mSensorName, mCamCfgDir, mTuningCfg, mLardTagCfg,
                                 mNvmPath, mCameraModuleToAiqbMap, nvmData);
    }
    return mCpfStore->getCpfAndCmc(ispData, aiqData, otherData, cmcHandle, mode, cmcData);
}

status_t AiqInitData::loadNvm()
{
    LOG1("@%s", __func__);

    if (mNvmPath.length() == 0) {
        LOG1("NVM dirctory from config is null");
        return UNKNOWN_ERROR;
    }

    LOG2("NVM data for %s is located in %s", mSensorName.c_str(), mNvmPath.c_str());

    FILE* nvmFile = fopen(mNvmPath.c_str(), "rb");
    CheckError(!nvmFile, UNKNOWN_ERROR, "Failed to open NVM file: %s", mNvmPath.c_str());

    fseek(nvmFile, 0, SEEK_END);
    int nvmDataSize = std::min(static_cast<int>(ftell(nvmFile)), mMaxNvmSize);
    fseek(nvmFile, 0, SEEK_SET);

    std::unique_ptr<char[]> nvmData(new char[nvmDataSize]);
    LOG2("NVM data size: %d bytes", nvmDataSize);

    int ret = fread(nvmData.get(), nvmDataSize, 1, nvmFile);
    fclose(nvmFile);
    CheckError(ret == 0, UNKNOWN_ERROR, "Cannot read nvm data");

    mNvmDataBuf = std::move(nvmData);
    mNvmData.data = mNvmDataBuf.get();
    mNvmData.size = nvmDataSize;

    return OK;
}

ia_binary_data* AiqInitData::getNvm()
{
    if (!mNvmData.data || mNvmData.size == 0) {
        loadNvm();
    }

    return mNvmData.data ? &mNvmData : nullptr;
}

ia_binary_data* AiqInitData::getAiqd(TuningMode mode) {
    if (mAiqdDataMap.find(mode) == mAiqdDataMap.end()) {
        mAiqdDataMap[mode] = new AiqdData(mode, mSensorName);
    }
    AiqdData* aiqd = mAiqdDataMap[mode];
    CheckError(!aiqd, nullptr, "@%s, aiqd is nullptr", __func__);

    return aiqd->getAiqd();
}

void AiqInitData::saveAiqd(TuningMode mode, const ia_binary_data& data) {
    if (mAiqdDataMap.find(mode) == mAiqdDataMap.end()) {
        mAiqdDataMap[mode] = new AiqdData(mode, mSensorName);
    }

    AiqdData* aiqd = mAiqdDataMap[mode];
    CheckError(!aiqd, VOID_VALUE, "@%s, aiqd is nullptr", __func__);

    aiqd->saveAiqd(data);
}

void* AiqInitData::getMknHandle(void)
{
    return mMakerNote->getMknHandle();
}

int AiqInitData::saveMakernoteData(camera_makernote_mode_t makernoteMode, int64_t sequence)
{
    return mMakerNote->saveMakernoteData(makernoteMode, sequence);
}

void AiqInitData::updateMakernoteTimeStamp(int64_t sequence, uint64_t timestamp)
{
    mMakerNote->updateTimestamp(sequence, timestamp);
}

void AiqInitData::acquireMakernoteData(uint64_t timestamp, Parameters *param)
{
    mMakerNote->acquireMakernoteData(timestamp, param);
}

}
