/*
 * 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()
{
    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, nullptr);
            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, nullptr);
        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)
{
    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();

        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) {
        mCpfStore = new CpfStore(mSensorName, mCamCfgDir, mTuningCfg, mLardTagCfg,
                                 mNvmPath, mCameraModuleToAiqbMap);
    }
    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);
}

}
