/*
 * Copyright 2024 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

#include <kylin-ai/ai-engine/aiengine.h>

#include "docimgrec_triton_client/client.h"
#include "image_binaryzation/client.h"
#include "matting_triton_client/client.h"
#include "ondevicevisioncapabilityengine.h"

namespace ai_engine::core_ai::vision {

OndeviceVisionImageProcessEngine::OndeviceVisionImageProcessEngine()
    : ddcpClient_(new DdcpTritonClient("localhost:8000")),
      mattingClient_(new MattingTritonClient("localhost:8000")),
      binImage_(new BinaryImage) {
    binarizeImageRunning_.store(false, std::memory_order_release);
    MattingRunning_.store(false, std::memory_order_release);
}

OndeviceVisionImageProcessEngine::~OndeviceVisionImageProcessEngine() {
    delete mattingClient_;
    delete ddcpClient_;
    delete binImage_;
}

void OndeviceVisionImageProcessEngine::setImageBinaryResultCallback(ImageResultCallback callback) {
    imageBinaryzationResultCallback_ = std::move(callback);

    if (binImage_ == nullptr) {
        return;
    }
}

result::AiEngineBaseResult OndeviceVisionImageProcessEngine::binarizeImageFromImageFile(
    const std::string &imageFilePath) {
    std::lock_guard<std::mutex> lock(binImageMutex_);
    binarizeImageRunning_.store(true, std::memory_order_release);
    result::AiEngineBaseResult error;
    error.success = true;
    ImgBase64Result res = binImage_->binaryImageRequestByPath(imageFilePath);
    if (res.errorCode != -1) {
        error.success = false;
        error.error = ai_engine::EngineError((int)VisionEngineErrorCode::ImageFileReadError, res.errorMessage);
        binarizeImageRunning_.store(false, std::memory_order_release);
        return error;
    }
    ImageResult result;
    result.success = true;
    result.imageFormat = res.format;
    result.imageBase64Data = res.base64Result;
    result.modelName = modelName_;
    if (binarizeImageRunning_.load(std::memory_order_acquire) == true) imageBinaryzationResultCallback_(result);
    binarizeImageRunning_.store(false, std::memory_order_release);

    return error;
}

result::AiEngineBaseResult OndeviceVisionImageProcessEngine::binarizeImageFromBase64ImageData(
    const std::string &imageBase64Data) {
    std::lock_guard<std::mutex> lock(binImageMutex_);
    binarizeImageRunning_.store(true, std::memory_order_release);
    result::AiEngineBaseResult error;
    error.success = true;
    ImgBase64Result res = binImage_->binaryImageRequestByBase64(imageBase64Data.c_str());
    if (res.errorCode != -1) {
        error.success = false;
        error.error = ai_engine::EngineError((int)VisionEngineErrorCode::ImageFileReadError, res.errorMessage);
        binarizeImageRunning_.store(false, std::memory_order_release);
        return error;
    }
    ImageResult result;
    result.success = true;
    result.imageFormat = res.format;
    result.imageBase64Data = res.base64Result;
    result.modelName = modelName_;
    if (binarizeImageRunning_.load(std::memory_order_acquire) == true) imageBinaryzationResultCallback_(result);
    binarizeImageRunning_.store(false, std::memory_order_release);
    return error;
}

std::string OndeviceVisionImageProcessEngine::modelInfo() const {
    const char *info = R"(
    {
        "vendor": "",
        "models": [
            {
                "name": "vision",
                "subConfig": [],
                "debName": "",
                "is3rdModel": false
            }
        ]
    }
    )";
    return info;
}

result::AiEngineBaseResult OndeviceVisionImageProcessEngine::initImageBinaryModule() {
    result::AiEngineBaseResult error;
    error.success = true;

    return error;
}

result::AiEngineBaseResult OndeviceVisionImageProcessEngine::destroyImageBinaryModule() {
    result::AiEngineBaseResult error;
    error.success = true;

    return error;
}

void OndeviceVisionImageProcessEngine::stopImageBinarization() {
    if (binarizeImageRunning_.load(std::memory_order_acquire)) {
        binarizeImageRunning_.store(false, std::memory_order_release);
        ImageResult result;
        result.success = true;
        result.imageFormat = "";
        result.imageBase64Data = "";
        result.modelName = modelName_;
        imageBinaryzationResultCallback_(result);
    }
}

}  // namespace ai_engine::core_ai::vision
