#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/core.hpp"
#include "opencv2/calib3d.hpp"
#include "libqr.h"

using namespace cv;
using namespace std;

static
std::string make_resp(bool ok, string err, float clarity, int angle = -1, string qrcode = "", double elapsed = 0)
{
    char buf[512];
    snprintf(buf, sizeof(buf), R"({ "ok": %s, "err": "%s", "qrcode": "%s", "clarity": %lf, "angle": %d, "elapsed": %lf })",
             ok ? "true" : "false",
             err.c_str(),
             qrcode.c_str(),
             clarity,
             angle,
             elapsed
            );
    return string(buf);
}


extern "C" {
const char *qrtool_angle(uint8_t *data,
                         int width, int height,
                         uint8_t *mid_left_area,
                         float camera_sensitivity) {
    ProcessState ps;
    ps.sobel_thres = camera_sensitivity * 3;
    auto start = std::chrono::system_clock::now();
    static char ret[512];
    Mat orig(Size(width, height), CV_8UC4, data);
    string qrcode, err;
    float angle;
    auto ok = emblem_dot_angle(ps, orig, angle, qrcode, err);
    auto end = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed = end-start;
    auto x = make_resp(ok, err, ps.clarity, angle, qrcode, elapsed.count());
    if (mid_left_area) {
        if (!ps.left_mid_area.empty()) {
            Mat lma;
            ps.left_mid_area.convertTo(lma, CV_8UC4);
            resize(lma, lma, Size(32 ,32));
            memset(mid_left_area, 255, 32 * 32 * 4);
            memcpy(mid_left_area, lma.ptr(), 32 * 32 * 4);
        } else {
            memset(mid_left_area, 55, 32 * 32 * 4);
        }
    }
    snprintf(ret, 512, "%s", x.c_str());
    return ret;
}
}
