/*
 * 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 "client.h"
#include <nlohmann/json.hpp>

using namespace std;
namespace nl = nlohmann;
namespace tc = triton::client;

ImgBase64Result BinaryImage::binaryImageRequestByPath(string ImagePath) {
    ImgBase64Result res;

    // 使用 ifstream 检查文件是否存在
    std::ifstream file(ImagePath, std::ios::binary);
    if (!file.is_open()) {
        // 如果文件无法打开，返回错误信息
        res.errorCode = 1;
        res.errorMessage = "Can not open file";
        return res;
    }

    unsigned char head[12] = {0};
    file.read((char *)head, 8);
    std::string imgFormat = getFormatFromHeader(head);
    cv::Mat src_img = cv::imread(ImagePath);
    res = binaryImageRequestByImage(src_img, imgFormat);

    return res;
}

ImgBase64Result BinaryImage::binaryImageRequestByBase64(const char *ImageData) {
    ImgBase64Result res;

    if (strlen(ImageData) < 1) {
        res.errorCode = 1;
        res.errorMessage = "base64_string size error";
        return res;
    }
    std::string decoded_data = base64_decode(ImageData);
    unsigned char head[12] = {0};
    if (decoded_data.size() < 8) {
        res.errorCode = 1;
        res.errorMessage = "decoded_data size error";
        return res;
    }
    memcpy(head, decoded_data.data(), 8);
    std::string imgFormat = getFormatFromHeader(head);
    std::vector<uchar> data(decoded_data.begin(), decoded_data.end());
    cv::Mat Image = cv::imdecode(data, cv::IMREAD_COLOR);
    res = binaryImageRequestByImage(Image, imgFormat);

    return res;
}

std::string BinaryImage::GetConfigValue(const char *key, const char *engine) { return ""; }

ImgBase64Result BinaryImage::binaryImageRequestByImage(cv::Mat Image, std::string imgFormat) {
    ImgBase64Result res;
    if (Image.empty()) {
        res.errorCode = 2;
        res.errorMessage = "Image is empty";
        // 可以执行后续的图像处理操作
        std::cout << __LINE__ << " res.errorMessage: " << res.errorMessage << std::endl;
        return res;
    }

    cv::Mat opMat = Image.clone();
    // 灰度
    cv::Mat grayMat = opMat.clone();
    if (opMat.channels() != 1) {
        cvtColor(opMat, grayMat, cv::COLOR_BGR2GRAY);
    }
    // 双边滤波只支持8位无符号整型（CV_8U）和32位浮点型（CV_32F）的图像格式
    if (grayMat.type() != CV_8U || grayMat.type() != CV_32F) {
        grayMat.convertTo(grayMat, CV_8U);
    }
    // 双边滤波-降噪
    cv::Mat filtMat = grayMat.clone();
    bilateralFilter(grayMat, filtMat, 10, 10, 10);  // src和dst需不同

    // 黑白二值图像
    cv::Mat binaryMat = filtMat.clone();
    double maxValue = 255;
    cv::adaptiveThreshold(filtMat, binaryMat, maxValue,
                          cv::ADAPTIVE_THRESH_GAUSSIAN_C,  // 自动阈值计算
                          cv::THRESH_BINARY,
                          25,  // blockSize 必须是奇数
                          9);  // -C 用于微调阈值

    std::string res_base64 = MatToBase64(binaryMat);
    res.base64Result = res_base64;
    res.format = imgFormat;  // 图片format
    res.errorCode = -1;      // 假设成功时 errorCode 为 -1
    res.errorMessage.clear();

    return res;
}
