/* ============================================================
 *
 * This file is a part of digiKam project
 * https://www.digikam.org
 *
 * Date        : 2013-08-19
 * Description : Image Quality settings widget
 *
 * Copyright (C) 2013-2020 by Gilles Caulier <caulier dot gilles at gmail dot com>
 * Copyright (C) 2013-2014 by Gowtham Ashok <gwty93 at gmail dot com>
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation;
 * either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * ============================================================ */

#include "imagequalitysettings.h"

// Qt includes

#include <QCheckBox>
#include <QGroupBox>
#include <QGridLayout>
#include <QLabel>
#include <QVBoxLayout>
#include <QIcon>
#include <QApplication>
#include <QStyle>

// KDE includes

#include <klocalizedstring.h>

// Local includes

#include "dlayoutbox.h"
#include "picklabelwidget.h"
#include "dnuminput.h"
#include "imagequalitycontainer.h"

namespace Digikam
{

class Q_DECL_HIDDEN ImageQualitySettings::Private
{
public:

    explicit Private()
      : optionsView(nullptr),
        enableSorter(nullptr),
        useFullImage(nullptr),
        detectBlur(nullptr),
        detectNoise(nullptr),
        detectCompression(nullptr),
        detectExposure(nullptr),
        setRejected(nullptr),
        setPending(nullptr),
        setAccepted(nullptr),
        setSpeed(nullptr),
        setRejectedThreshold(nullptr),
        setPendingThreshold(nullptr),
        setAcceptedThreshold(nullptr),
        setBlurWeight(nullptr),
        setNoiseWeight(nullptr),
        setCompressionWeight(nullptr)
    {
    }

    DVBox*        optionsView;
    QCheckBox*    enableSorter;
    QCheckBox*    useFullImage;
    QCheckBox*    detectBlur;
    QCheckBox*    detectNoise;
    QCheckBox*    detectCompression;
    QCheckBox*    detectExposure;
    QCheckBox*    setRejected;
    QCheckBox*    setPending;
    QCheckBox*    setAccepted;

    DIntNumInput* setSpeed;
    DIntNumInput* setRejectedThreshold;
    DIntNumInput* setPendingThreshold;
    DIntNumInput* setAcceptedThreshold;
    DIntNumInput* setBlurWeight;
    DIntNumInput* setNoiseWeight;
    DIntNumInput* setCompressionWeight;
};

// --------------------------------------------------------

ImageQualitySettings::ImageQualitySettings(QWidget* const parent)
    : QWidget(parent),
      d(new Private)
{
    QVBoxLayout* const layout = new QVBoxLayout(this);

    d->enableSorter = new QCheckBox(i18n("Enable Image Quality Sorting (Experimental)"), this);
    d->enableSorter->setWhatsThis(i18n("Enable this option to assign automatically Pick Labels based on image quality."));

    d->optionsView  = new DVBox(this);

    layout->addWidget(d->enableSorter);
    layout->addWidget(d->optionsView);

    // ------------------------------------------------------------------------------

    d->detectBlur        = new QCheckBox(i18n("Detect Blur"), d->optionsView);
    d->detectBlur->setWhatsThis(i18n("Detect the amount of blur in the images passed to it"));

    d->detectNoise       = new QCheckBox(i18n("Detect Noise"), d->optionsView);
    d->detectNoise->setWhatsThis(i18n("Detect the amount of noise in the images passed to it"));

    d->detectCompression = new QCheckBox(i18n("Detect Compression"), d->optionsView);
    d->detectCompression->setWhatsThis(i18n("Detect the amount of compression in the images passed to it"));

    d->detectExposure    = new QCheckBox(i18n("Detect Under and Over Exposure"), d->optionsView);
    d->detectExposure->setWhatsThis(i18n("Detect if the images are under-exposed or over-exposed"));

    // ------------------------------------------------------------------------------

    DHBox* const hlay1      = new DHBox(d->optionsView);

    d->setRejected          = new QCheckBox(i18n("Assign 'Rejected' Label to Low Quality Pictures"), hlay1);
    d->setRejected->setWhatsThis(i18n("Low quality images detected by blur, noise, and compression analysis will be assigned to Rejected label."));

    QWidget* const hspace1  = new QWidget(hlay1);
    hlay1->setStretchFactor(hspace1, 10);

    QLabel* const workIcon1 = new QLabel(hlay1);
    workIcon1->setPixmap(QIcon::fromTheme(QLatin1String("flag-red")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize)));

    // ------------------------------------------------------------------------------

    DHBox* const hlay2      = new DHBox(d->optionsView);

    d->setPending           = new QCheckBox(i18n("Assign 'Pending' Label to Medium Quality Pictures"), hlay2);
    d->setPending->setWhatsThis(i18n("Medium quality images detected by blur, noise, and compression analysis will be assigned to Pending label."));

    QWidget* const hspace2  = new QWidget(hlay2);
    hlay2->setStretchFactor(hspace2, 10);

    QLabel* const workIcon2 = new QLabel(hlay2);
    workIcon2->setPixmap(QIcon::fromTheme(QLatin1String("flag-yellow")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize)));

    // ------------------------------------------------------------------------------

    DHBox* const hlay3      = new DHBox(d->optionsView);

    d->setAccepted          = new QCheckBox(i18n("Assign 'Accepted' Label to High Quality Pictures"), hlay3);
    d->setAccepted->setWhatsThis(i18n("High quality images detected by blur, noise, and compression analysis will be assigned to Accepted label."));

    QWidget* const hspace3  = new QWidget(hlay3);
    hlay3->setStretchFactor(hspace3, 10);

    QLabel* const workIcon3 = new QLabel(hlay3);
    workIcon3->setPixmap(QIcon::fromTheme(QLatin1String("flag-green")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize)));

    // ------------------------------------------------------------------------------

    QWidget* const settings = new QWidget(d->optionsView);
    QGridLayout* const glay = new QGridLayout(settings);

    QLabel* const lbl1      = new QLabel(i18n("Speed:"), settings);
    lbl1->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    d->setSpeed             = new DIntNumInput(settings);
    d->setSpeed->setDefaultValue(5);
    d->setSpeed->setRange(1, 3, 1);
    d->setSpeed->setWhatsThis(i18n("Tradeoff between speed and accuracy of sorting algorithm"));

    QLabel* const lbl2      = new QLabel(i18n("Rejected threshold:"), settings);
    lbl2->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    d->setRejectedThreshold = new DIntNumInput(settings);
    d->setRejectedThreshold->setDefaultValue(5);
    d->setRejectedThreshold->setRange(1, 100, 1);
    d->setRejectedThreshold->setWhatsThis(i18n("Threshold below which all pictures are assigned Rejected Label"));

    QLabel* const lbl3 = new QLabel(i18n("Pending threshold:"), settings);
    lbl3->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    d->setPendingThreshold  = new DIntNumInput(settings);
    d->setPendingThreshold->setDefaultValue(5);
    d->setPendingThreshold->setRange(1, 100, 1);
    d->setPendingThreshold->setWhatsThis(i18n("Threshold below which all pictures are assigned Pending Label"));

    QLabel* const lbl4      = new QLabel(i18n("Accepted threshold:"), settings);
    lbl4->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    d->setAcceptedThreshold = new DIntNumInput(settings);
    d->setAcceptedThreshold->setDefaultValue(5);
    d->setAcceptedThreshold->setRange(1, 100, 1);
    d->setAcceptedThreshold->setWhatsThis(i18n("Threshold above which all pictures are assigned Accepted Label"));

    QLabel* const lbl5      = new QLabel(i18n("Blur Weight:"), settings);
    lbl5->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    d->setBlurWeight        = new DIntNumInput(settings);
    d->setBlurWeight->setDefaultValue(5);
    d->setBlurWeight->setRange(1, 100, 1);
    d->setBlurWeight->setWhatsThis(i18n("Weight to assign to Blur Algorithm"));

    QLabel* const lbl6      = new QLabel(i18n("Noise Weight:"), settings);
    lbl6->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    d->setNoiseWeight       = new DIntNumInput(settings);
    d->setNoiseWeight->setDefaultValue(5);
    d->setNoiseWeight->setRange(1, 100, 1);
    d->setNoiseWeight->setWhatsThis(i18n("Weight to assign to Noise Algorithm"));

    QLabel* const lbl7      = new QLabel(i18n("Compression Weight:"), settings);
    lbl7->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    d->setCompressionWeight = new DIntNumInput(settings);
    d->setCompressionWeight->setDefaultValue(5);
    d->setCompressionWeight->setRange(1, 100, 1);
    d->setCompressionWeight->setWhatsThis(i18n("Weight to assign to Compression Algorithm"));

    glay->addWidget(lbl1,                     0, 0, 1, 1);
    glay->addWidget(d->setSpeed,              0, 1, 1, 1);
    glay->addWidget(lbl2,                     1, 0, 1, 1);
    glay->addWidget(d->setRejectedThreshold,  1, 1, 1, 1);
    glay->addWidget(lbl3,                     2, 0, 1, 1);
    glay->addWidget(d->setPendingThreshold,   2, 1, 1, 1);
    glay->addWidget(lbl4,                     3, 0, 1, 1);
    glay->addWidget(d->setAcceptedThreshold,  3, 1, 1, 1);
    glay->addWidget(lbl5,                     4, 0, 1, 1);
    glay->addWidget(d->setBlurWeight,         4, 1, 1, 1);
    glay->addWidget(lbl6,                     5, 0, 1, 1);
    glay->addWidget(d->setNoiseWeight,        5, 1, 1, 1);
    glay->addWidget(lbl7,                     6, 0, 1, 1);
    glay->addWidget(d->setCompressionWeight,  6, 1, 1, 1);
    glay->setRowStretch(7, 10);

    connect(d->enableSorter, SIGNAL(toggled(bool)),
            d->optionsView, SLOT(setEnabled(bool)));

    readSettings();
}

ImageQualitySettings::~ImageQualitySettings()
{
    delete d;
}

void ImageQualitySettings::applySettings()
{
    ImageQualityContainer imq;

    imq.enableSorter      = d->enableSorter->isChecked();
    imq.speed             = d->setSpeed->value();
    imq.detectBlur        = d->detectBlur->isChecked();
    imq.detectNoise       = d->detectNoise->isChecked();
    imq.detectCompression = d->detectCompression->isChecked();
    imq.detectExposure    = d->detectExposure->isChecked();
    imq.lowQRejected      = d->setRejected->isChecked();
    imq.mediumQPending    = d->setPending->isChecked();
    imq.highQAccepted     = d->setAccepted->isChecked();
    imq.rejectedThreshold = d->setRejectedThreshold->value();
    imq.pendingThreshold  = d->setPendingThreshold->value();
    imq.acceptedThreshold = d->setAcceptedThreshold->value();
    imq.blurWeight        = d->setBlurWeight->value();
    imq.noiseWeight       = d->setNoiseWeight->value();
    imq.compressionWeight = d->setCompressionWeight->value();

    imq.writeToConfig();
}

void ImageQualitySettings::readSettings()
{
    ImageQualityContainer imq;
    imq.readFromConfig();

    d->enableSorter->setChecked(imq.enableSorter);
    d->setSpeed->setValue(imq.speed);
    d->detectBlur->setChecked(imq.detectBlur);
    d->detectNoise->setChecked(imq.detectNoise);
    d->detectCompression->setChecked(imq.detectCompression);
    d->detectExposure->setChecked(imq.detectExposure);
    d->setRejected->setChecked(imq.lowQRejected);
    d->setPending->setChecked(imq.mediumQPending);
    d->setAccepted->setChecked(imq.highQAccepted);
    d->setRejectedThreshold->setValue(imq.rejectedThreshold);
    d->setPendingThreshold->setValue(imq.pendingThreshold);
    d->setAcceptedThreshold->setValue(imq.acceptedThreshold);
    d->setBlurWeight->setValue(imq.blurWeight);
    d->setNoiseWeight->setValue(imq.noiseWeight);
    d->setCompressionWeight->setValue(imq.compressionWeight);

    d->optionsView->setEnabled(imq.enableSorter);
}

} // namespace Digikam
