/*
 * Copyright (C) 2019-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 "IntelFaceDetection"
#include "modules/algowrapper/IntelFaceDetection.h"

#include <string.h>

#include <algorithm>

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

namespace icamera {
IntelFaceDetection::IntelFaceDetection() : mFDHandle(nullptr), mMaxFacesNum(0) {
    LOG1("@%s", __func__);
}

IntelFaceDetection::~IntelFaceDetection() {
    LOG1("@%s", __func__);
}

status_t IntelFaceDetection::init(FaceDetectionInitParams* pData, int dataSize) {
    LOG1("@%s, pData:%p, dataSize:%d", __func__, pData, dataSize);
    CheckError(!pData, UNKNOWN_ERROR, "pData is nullptr");
    CheckError(dataSize < static_cast<int>(sizeof(FaceDetectionInitParams)), UNKNOWN_ERROR,
               "buffer is small");

    mMaxFacesNum = std::min(pData->max_face_num, static_cast<unsigned int>(MAX_FACES_DETECTABLE));
    LOG2("@%s, mMaxFacesNum:%d, cameraId:%d", __func__, mMaxFacesNum, pData->cameraId);

    pvl_err faceRet = pvl_face_detection_create(nullptr, &mFDHandle);
    CheckError(faceRet != pvl_success, UNKNOWN_ERROR,
               "@%s, Failed to pvl_face_detection_create,faceRet:%d", __func__, faceRet);

    pvl_face_detection_parameters params = {};
    pvl_face_detection_default_parameters(normal, &params);
    params.max_num_faces = mMaxFacesNum;
    faceRet = pvl_face_detection_set_parameters(mFDHandle, &params);
    CheckError(faceRet != pvl_success, UNKNOWN_ERROR,
               "@%s, Failed to pvl_face_detection_set_paramters,faceRet:%d", __func__, faceRet);

    LOG2("@%s, max_num_faces:%d, rip_range:%d, num_rollover_frames:%d", __func__,
         params.max_num_faces, params.rip_range, params.num_rollover_frames);

    return OK;
}

status_t IntelFaceDetection::deinit(FaceDetectionDeinitParams* pData, int dataSize) {
    CheckError(!pData, UNKNOWN_ERROR, "pData is nullptr");
    CheckError(dataSize < static_cast<int>(sizeof(FaceDetectionDeinitParams)), UNKNOWN_ERROR,
               "buffer is small");
    LOG1("@%s, cameraId:%d", __func__, pData->cameraId);

    if (mFDHandle) {
        pvl_face_detection_destroy(mFDHandle);
        mFDHandle = nullptr;
    }
    return OK;
}

void IntelFaceDetection::convertCoordinate(int faceId, int width, int height, const pvl_rect& src,
                                           pvl_rect* dst) {
    CheckError(!dst, VOID_VALUE, "dst is nullptr");

    const camera_coordinate_system_t iaCoordinate = {IA_COORDINATE_LEFT, IA_COORDINATE_TOP,
                                                     IA_COORDINATE_RIGHT, IA_COORDINATE_BOTTOM};
    const camera_coordinate_system_t faceCoordinate = {0, 0, width, height};

    camera_coordinate_t topLeft =
        AiqUtils::convertCoordinateSystem(faceCoordinate, iaCoordinate, {src.left, src.top});
    camera_coordinate_t bottomRight =
        AiqUtils::convertCoordinateSystem(faceCoordinate, iaCoordinate, {src.right, src.bottom});

    *dst = {topLeft.x, topLeft.y, bottomRight.x, bottomRight.y};
    LOG2("@%s, face:%d, dst left:%d, top:%d, right:%d, bottom:%d", __func__, faceId, dst->left,
         dst->top, dst->right, dst->bottom);
}

FaceDetectionRunParams* IntelFaceDetection::prepareRunBuffer(unsigned int index) {
    LOG1("@%s", __func__);
    CheckError(index >= MAX_STORE_FACE_DATA_BUF_NUM, nullptr, "@%s, index is error %d", __func__,
               index);
    CheckError(!mFDHandle, nullptr, "mFDHandle is nullptr");

    return &mMemRunBufs[index];
}

status_t IntelFaceDetection::run(pvl_image* pImage, FaceDetectionResult* fdResults) {
    LOG1("@%s, pImage:%p", __func__, pImage);
    CheckError(!pImage, UNKNOWN_ERROR, "pData is nullptr");
    CheckError(!mFDHandle, UNKNOWN_ERROR, "mFDHandle is nullptr");

    int32_t fdRet =
        pvl_face_detection_run_in_preview(mFDHandle, pImage, fdResults->faceResults, mMaxFacesNum);
    fdResults->faceNum = (fdRet > 0) ? fdRet : 0;
    LOG1("@%s, fdRet:%d, detected face number:%d, w:%d, h:%d", __func__, fdRet, fdResults->faceNum,
         pImage->width, pImage->height);
    for (int i = 0; i < fdResults->faceNum; i++) {
        LOG2("@%s, face:%d rect, left:%d, top:%d, right:%d, bottom:%d", __func__, i,
             fdResults->faceResults[i].rect.left, fdResults->faceResults[i].rect.top,
             fdResults->faceResults[i].rect.right, fdResults->faceResults[i].rect.bottom);
        LOG2("@%s, confidence:%d, rip_angle:%d, rop_angle:%d, tracking_id:%d", __func__,
             fdResults->faceResults[i].confidence, fdResults->faceResults[i].rip_angle,
             fdResults->faceResults[i].rop_angle, fdResults->faceResults[i].tracking_id);
    }

    for (int i = 0; i < fdResults->faceNum; i++) {
        convertCoordinate(i, pImage->width, pImage->height, fdResults->faceResults[i].rect,
                          &fdResults->faceResults[i].rect);
    }

    return OK;
}

status_t IntelFaceDetection::run(FaceDetectionRunParams* fdRunParams, int dataSize, void* addr) {
    LOG1("@%s, fdRunParams:%p, dataSize:%d, addr:%p", __func__, fdRunParams, dataSize, addr);
    CheckError(!fdRunParams, UNKNOWN_ERROR, "pData is nullptr");
    CheckError(dataSize < static_cast<int>(sizeof(FaceDetectionRunParams)), UNKNOWN_ERROR,
               "buffer is small");
    CheckError(!mFDHandle, UNKNOWN_ERROR, "mFDHandle is nullptr");

    pvl_image image;
    image.size = fdRunParams->size;
    image.width = fdRunParams->width;
    image.height = fdRunParams->height;
    image.format = fdRunParams->format;
    image.stride = fdRunParams->stride;
    image.rotation = fdRunParams->rotation;
    if (addr) {
        image.data = const_cast<uint8_t*>(static_cast<uint8_t*>(addr));
    } else {
        image.data = const_cast<uint8_t*>(fdRunParams->data);
    }

    return run(&image, &fdRunParams->results);
}
}  // namespace icamera
