// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
#include <iostream>
#include <vector>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <chrono>
#include <filesystem>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "opencv2/objdetect.hpp"
#include <opencv2/dnn.hpp>

#include "mq_worker.h"
#include "http.h"
#include "libqr.h"

static
int detect_cmd(char **argv, int argc)
{
    char *file = argv[0];
    auto orig = imread(file);
    QRCodeDetector detector;

    Mat points;
    Mat straight;
    auto r = detector.detectAndDecode(orig, points, straight);
    printf("r: %s\n", r.c_str());
    printf("points: %d %d\n", points.rows, points.cols);
    for (int i = 0; i < points.cols; i++) {
        printf("%f ", points.at<float>(0, i));
    }
    printf("\n");
    return 0;
}

static
int angle_cmd(char **argv, int argc)
{
    char *file = argv[0];
    printf("file: %s\n", file);
    Mat orig = imread(file);
    string qrcode, err;
    float angle;
    ProcessState ps;
    auto r = emblem_dot_angle(ps, orig, angle, qrcode, err);

    if (!r) {
        cerr << r << ":" << err << endl;
        return 1;
    }
    printf("angle: %.1f\n", angle);
    printf("qrcode: %s\n", qrcode.c_str());
    return 0;
}

static
int dot_cmd(char **argv, int argc)
{
    ProcessState ps;
    char *file = argv[0];
    printf("file: %s\n", file);
    Mat orig = imread(file);
    string qrcode, err;
    float angle;
    auto r = emblem_dot_angle(ps, orig, angle, qrcode, err);

    if (!r) {
        cerr << r << ":" << err << endl;
        return 1;
    }
    string outfile = string(file) + ".dot.jpg";
    printf("angle: %.1f\n", angle);
    printf("qrcode: %s\n", qrcode.c_str());
    printf("saving dot file: %s\n", outfile.c_str());
    imwrite(outfile, ps.left_mid_area);
    return 0;
}


static
void usage(const char *name, vector<string> &cmds)
{
    printf("usage: %s <cmd> <arg0>\n", name);
    printf("or for 2 args: %s <cmd> <arg0> <arg1>\n", name);
    printf("possible commands:\n");
    for (auto cmd: cmds) {
        printf("  %s\n", cmd.c_str());
    }
}

static
int roi_verify_cmd(char **argv, int argc)
{
    char *model_path = argv[0];
    char *input_file = argv[1];
    Mat input_img = imread(input_file);
    cv::dnn::Net net = cv::dnn::readNetFromONNX(model_path);
    if (net.empty()) {
        std::cerr << "Failed to load ONNX model!" << std::endl;
        return -1;
    }
    cv::Mat blob;
    cv::resize(input_img, input_img, cv::Size(128, 64));  // 调整图像大小
    cv::dnn::blobFromImage(input_img, blob, 1.0 / 255.0, cv::Size(64, 128), cv::Scalar(0.485, 0.456, 0.406), true, false);
    blob = (blob - cv::Scalar(0.485, 0.456, 0.406)) / cv::Scalar(0.229, 0.224, 0.225);  // 归一化
    net.setInput(blob);
    cv::Mat output = net.forward();
    float* data = (float*)output.data;
    int class_id = std::max_element(data, data + output.total()) - data;  // 找到最大概率的类别
    float confidence = data[class_id];
    std::cout << "Predicted class: " << class_id << ", Confidence: " << confidence << std::endl;

    return 0;
}

#ifdef QRTOOL_MAIN
int main(int argc, char *argv[])
{
    string cmd = "help";
    if (argc > 1) {
        cmd = argv[1];
    }
    vector<string> cmds;

#define add_cmd(c, nargs) \
    do { \
        cmds.push_back(#c); \
        if (cmd == #c && argc >= 2 + nargs) return c##_cmd(&argv[2], argc - 2); \
    } while (0)

    add_cmd(detect, 1);
    add_cmd(angle, 1);
    usage(argv[0], cmds);
    return 1;
}
#endif
