#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <map>
#include <string>
#include <iostream>

using namespace std;
using namespace cv;

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include "../common.h"
#include "color_filter.h"
#include "adjust_image.h"

vector<SealInfo> extract_seal_main(const Mat& img, const vector<vector<double>>& det) {
    int i = 0;
    vector<SealInfo> seal_set;
    for (const auto& seal : det) {
        int x1 = int(seal[0]);
        int y1 = int(seal[1]);
        int x2 = int(seal[2]);
        int y2 = int(seal[3]);
        double conf = seal[4];
        if (conf < 0.6) {
            continue;
        }
        int shape = int(seal[5]);
        
        int roi_x = max(0, x1);
        int roi_y = max(0, y1);
        int roi_width = min(x2 - x1, img.cols - roi_x);
        int roi_height = min(y2 - y1, img.rows - roi_y);
        
        if (roi_width <= 0 || roi_height <= 0) {
            cout << "Warning: Invalid ROI for detection box, skipping" << endl;
            continue;
        }
        
        Mat cropped_img = img(Rect(roi_x, roi_y, roi_width, roi_height));

        auto [extracted_img, color_name] = color_fliter_process(cropped_img, 50);
        
        vector<Mat> channels;
        split(extracted_img, channels);
        Mat red_channel = channels[0];
        
        Scalar mean_val = mean(red_channel);
        double red_average = mean_val[0];
        if (red_average > 240) {
            continue;
        }
        
        SealInfo seal_info;
        seal_info.x1 = x1;
        seal_info.y1 = y1;
        seal_info.x2 = x2;
        seal_info.y2 = y2;
        seal_info.conf = conf;
        seal_info.shape = shape;
        seal_info.cropped_img = cropped_img;
        seal_info.extracted_img = extracted_img;
        seal_info.color_name = color_name;

        ShapeInfo si;
        if (shape >= 0 && shape < 5) {
            si.type = SHAPETYPE_NAMES[shape];
        } else {
            si.type = "unknown";
        }
        
        int width = x2 - x1;
        int height = y2 - y1;
        si.minAreaRect = {{width / 2.0f, height / 2.0f}, {float(width), float(height)}, 0};
        
        auto [adj_img, angle, new_si] = adjust_img(seal_info.extracted_img, ShapeInfo(si.type, si.minAreaRect, si.points, si.ignores, si.needInits, si.implement));
        seal_info.shape_info = ShapeInfo(new_si.type, new_si.minAreaRect, new_si.points, new_si.ignores, new_si.needInits, new_si.implement);
        seal_info.angle = angle;
        seal_info.adj_img = adj_img;
        
        seal_set.push_back(seal_info);
    }
    
    // 存储到单例类中，实现数据共享
    seal_data::SealDataManager::getInstance().setSealSet(seal_set);
    
    return seal_set;
}

// int main() {
//     // TODO: 修改为你的图片路径
//     string img_path = "..\\..\\image\\2.png";
//     
//     Mat img = imread(img_path);
//     if (img.empty()) {
//         cout << "Error: Cannot read image " << img_path << endl;
//         return 1;
//     }
//     
//     cout << "Image dimensions: " << img.cols << "x" << img.rows << endl;
//     
//     vector<vector<double>> det = {{256.0, 384.0, 471.0, 592.0, 0.980, 2},
//                                  {511.0, 423.0, 665.0, 581.0, 0.969, 2}};
//     
//     cout << "Number of detection boxes: " << det.size() << endl;
//     for (const auto& seal : det) {
//         cout << "Detection box: x1=" << seal[0] << ", y1=" << seal[1] << ", x2=" << seal[2] << ", y2=" << seal[3] << endl;
//     }
//     
//     vector<SealInfo> seal_info = extract_seal_main(img, det);
//     
//     for (size_t i = 0; i < seal_info.size(); ++i) {
//         // TODO: 修改为你的输出路径
//         string filename = "test_image\\extracted_seal_";
//         filename += to_string(i) + ".png";
//         imwrite(filename, seal_info[i].adj_img);
//         cout << "Test seal " << i << " saved to: " << filename << endl;
//         cout << "  Shape: " << seal_info[i].shape_info.type << endl;
//         cout << "  Center: (" << seal_info[i].shape_info.minAreaRect.center.x << ", " << seal_info[i].shape_info.minAreaRect.center.y << ")" << endl;
//         cout << "  Size: (" << seal_info[i].shape_info.minAreaRect.size.width << ", " << seal_info[i].shape_info.minAreaRect.size.height << ")" << endl;
//         cout << "  Angle: " << seal_info[i].angle << endl;
//     }
//     
//     return 0;
// }

