/*
 * 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& aiqbNameFromModule,
                   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 (!aiqbNameFromModule.empty()) {
            aiqbName.assign(aiqbNameFromModule);
            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();
}

/**
 * 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;
}

int AiqInitData::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;
}

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, std::string* camModuleName,
                         std::unordered_map<std::string, std::string>& camModuleToAiqbMap) :
    mSensorName(sensorName),
    mCamCfgDir(camCfgDir),
    mMaxNvmSize(maxNvmSize),
    mTuningCfg(tuningCfg),
    mLardTagCfg(lardTagCfg),
    mCpfStore(nullptr),
    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());

        if (!camModuleToAiqbMap.empty()) {
            std::string cameraModule;
            int ret = getCameraModuleFromEEPROM(mNvmPath, &cameraModule);
            if (ret == OK) {
                LOG1("@%s, cameraModule %s", __func__, cameraModule.c_str());
                if (camModuleToAiqbMap.find(cameraModule) != camModuleToAiqbMap.end()) {
                    mAiqbNameFromModule.assign(camModuleToAiqbMap[cameraModule]);
                    if (camModuleName) *camModuleName = cameraModule;
                }
            }
        }
    }
}

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,
                                 mAiqbNameFromModule, 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);
}

}
