#include <QDebug>
#include <QString>
#include <QtGui/QImage>

#include <cmath>
#include <iostream>
#include <vector>

#include <QDir>
#include <QFileInfo>

#include <libintl.h>
#define _(value) gettext(value)

#include "ImageProcessing.h"

using namespace DocumentScanner;

const QString GETTEXT_DOMAIN = "camerascanner.jonnius";

ImageProcessing::ImageProcessing()
    : m_store(*DocumentStore::instance())
{
    textdomain(GETTEXT_DOMAIN.toStdString().c_str());
    /* empty */
    // TODO define default params
    // TODO load params from config
}

void ImageProcessing::restoreCache()
{
    bool any = false;
    for (QString id : m_store.restoreCache()) {
        emit imageAdded(id);
        any = true;
    }

    if (any)
        emit userInfo(_("Session restored"));

    validateIsAnyFlags();
}

void ImageProcessing::addImage(const QString &imageURL)
{
    QString id = m_store.addDocument(imageURL);
    m_store.cacheDocument(id);
    emit imageAdded(id);
    validateIsAnyFlags();
    m_extractorConfig.addImageConfig(id);
}

void ImageProcessing::reprocessImage(const QString &id, bool colorMode, bool filterMode, int colorThr, float colorGain, float colorBias)
{
    qDebug() << "reprocess image " << id << " with following values:" << colorMode << filterMode << colorThr << colorGain << colorBias;
    ONSExtractorConfig conf;
    conf.colorMode = colorMode;
    conf.filterMode = filterMode;
    conf.colorThr = colorThr * 100.0 + 150.0;
    conf.colorGain = colorGain;
    conf.colorBias = colorBias * 100.0;

    m_extractorConfig.editImageConfig(id, conf);

    m_store.reprocessDocument(id, conf);
    validateIsAnyFlags();
    emit imageUpdated(id);
}

void ImageProcessing::removeImage(const QString &id)
{
    m_store.removeDocument(id);
    emit imageRemoved(id);
    m_extractorConfig.removeImageConfig(id);
    validateIsAnyFlags();
}

void ImageProcessing::removeAll()
{
    for (QString id : m_store.getIDs())
        removeImage(id);
    validateIsAnyFlags();
}

QString ImageProcessing::exportAsPdf(const QString &id) const
{
    QStringList ids = { id };
    return m_store.exportPdf(ids);
}

QString ImageProcessing::exportAllAsPdf() const
{
    return m_store.exportPdf(m_store.getIDs());
}

QString ImageProcessing::exportAsImage(const QString &id) const
{
    return m_store.getImageURL(id);
}

QStringList ImageProcessing::exportAllAsImages() const
{
    QStringList ids = m_store.getIDs();
    QStringList urls;
    for (QString id : ids) {
        urls << m_store.getImageURL(id);
    }
    return urls;
}

bool ImageProcessing::isDocument(const QString &id) const
{
    return m_store.isExtractedDoc(id);
}

bool ImageProcessing::isAnyImage() const
{
    return m_isAnyImage;
}

bool ImageProcessing::isAnyDocument() const
{
    return m_isAnyDocument;
}

void ImageProcessing::validateIsAnyFlags()
{
    bool isAnyImage = false;
    bool isAnyDocument = false;
    QStringList ids = m_store.getIDs();
    for (QString id : ids) {
        isAnyImage = true;
        if (isDocument(id)) {
            isAnyDocument = true;
        }
    }

    if (isAnyImage != m_isAnyImage) {
        m_isAnyImage = isAnyImage;
        emit isAnyImageChanged();
    }

    if (isAnyDocument != m_isAnyDocument) {
        m_isAnyDocument = isAnyDocument;
        emit isAnyDocChanged();
    }
}

void ImageProcessing::loadSingleImageSettings(const QString &id)
{
    ONSExtractorConfig conf;
    conf = m_extractorConfig.loadImageConfig(id);
    qDebug() << "load image ImageProcessing" << id << " with following values:" << conf.colorMode << conf.filterMode << conf.colorThr << conf.colorGain << conf.colorBias;
    m_colorMode = conf.colorMode;
    emit colorModeChanged();
    m_filterMode = conf.filterMode;
    emit filterModeChanged();
    m_colorThr = (conf.colorThr - 150.0) / 100.0;
    emit colorThrChanged();
    m_colorGain = conf.colorGain;
    emit colorGainChanged();
    m_colorBias = conf.colorBias / 100.0;
    emit colorBiasChanged();
}

bool ImageProcessing::colorMode() const
{
    return m_colorMode;
}

bool ImageProcessing::filterMode() const
{
    return m_filterMode;
}

float ImageProcessing::colorThr() const
{
    return m_colorThr;
}

float ImageProcessing::colorGain() const
{
    return m_colorGain;
}

float ImageProcessing::colorBias() const
{
    return m_colorBias;
}
