#include "adjustpicturedialog.h"
#include "ui_adjustpicturedialog.h"
#include "utils/utils.h"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <string>
#include <opencv2/core/mat.hpp>
#include <QFileDialog>
#include <QMessageBox>
#include <zbar.h>

AdjustPictureDialog::AdjustPictureDialog(QWidget *parent, std::string imagePath)
    : QDialog(parent)
    , ui(new Ui::AdjustPictureDialog)
    , pixmap(QString::fromStdString(imagePath))
    , img(pixmap.toImage()){
    ui->setupUi(this);

    computeContrastLookupTable();

    scene = new QGraphicsScene(this);

    ui->graphicsView->setScene(scene);
    scene->addPixmap(pixmap);
}

AdjustPictureDialog::~AdjustPictureDialog() {
    delete ui;
}

void AdjustPictureDialog::accept() {
    QPixmap pixMap = ui->graphicsView->grab();
    pixMap.save(QString::fromStdString(get_path_relative_to_home(".local/share/checks_parser/temp.png")));

    std::string result = decode();

    if (result == "") {
        QMessageBox infoDialog;
        infoDialog.setText(tr("QR code was not detected on that image. Please edit it again or enter data manually"));
        infoDialog.setIcon(QMessageBox::Warning);
        infoDialog.setWindowTitle(tr("No QR code"));
        infoDialog.exec();
    } else {
        std::map<std::string, std::string> paramsMap;
        std::vector<std::string> dataSplit = split(result, "&");
        for (std::string &pair : dataSplit) {
            std::vector<std::string> values = split(pair, "=");
            paramsMap.insert(std::pair<std::string, std::string>(values[0], values[1]));
        }
        emit decodedData(paramsMap);
        QDialog::accept();
    }

}

std::string AdjustPictureDialog::decode() {
    cv::Mat im = cv::imread(get_path_relative_to_home(".local/share/checks_parser/temp.png"));

    zbar::ImageScanner scanner;
    scanner.set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);

    cv::Mat imGray;
    cv::cvtColor(im, imGray, cv::COLOR_BGR2GRAY);

    zbar::Image image(im.cols, im.rows, "Y800", (uchar *) imGray.data, im.cols * im.rows);
    scanner.scan(image);

    std::string result = "";

    for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
        result = symbol->get_data();
    }

    return result;
}

void AdjustPictureDialog::computeContrastLookupTable() {

    for (int contrastValue = 0; contrastValue < 100; ++contrastValue) {
        double contrast = contrastValue / 50.0;
        for (int i = 0; i < 256; ++i) {
            unsigned short correctedValue = std::clamp(static_cast<int>(128 + contrast * (i - 128)), 0, 255);
            contrastLUT[contrastValue].push_back(correctedValue);
        }
    }
}

void AdjustPictureDialog::on_contrastSlider_sliderMoved(int position) {
    QImage image = img.copy();

    uint32_t* pixels = reinterpret_cast<uint32_t*>(image.bits());
    int width = image.width();
    int height = image.height();

    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            QRgb rgb = pixels[y * width + x];
            pixels[y * width + x] = qRgba(
                contrastLUT[position][qRed(rgb)],
                contrastLUT[position][qGreen(rgb)],
                contrastLUT[position][qBlue(rgb)],
                qAlpha(rgb));
        }
    }

    scene->clear();
    scene->addPixmap(QPixmap::fromImage(image));
}