/*
 * This file is part of Krita
 *
 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include <webp/encode.h>

#include <kis_properties_configuration.h>

#include <KisSpinBoxI18nHelper.h>

#include "kis_wdg_options_webp.h"

KisWdgOptionsWebP::KisWdgOptionsWebP(QWidget *parent)
    : KisConfigWidget(parent)
{
    setupUi(this);

    // HACK ALERT!
    // QScrollArea contents are opaque at multiple levels
    // The contents themselves AND the viewport widget
    {
        scrollAreaWidgetContents->setAutoFillBackground(false);
        scrollAreaWidgetContents->parentWidget()->setAutoFillBackground(false);
    }

#if WEBP_ENCODER_ABI_VERSION < 0x020f
    qMin->setEnabled(false);
    qMax->setEnabled(false);
#endif

    preset->addItem(i18nc("WebP presets", "Default"), WEBP_PRESET_DEFAULT);
    preset->addItem(i18nc("WebP presets", "Portrait"), WEBP_PRESET_PICTURE);
    preset->addItem(i18nc("WebP presets", "Outdoor photo"), WEBP_PRESET_PHOTO);
    preset->addItem(i18nc("WebP presets", "Line drawing"), WEBP_PRESET_DRAWING);
    preset->addItem(i18nc("WebP presets", "Icon"), WEBP_PRESET_ICON);
    preset->addItem(i18nc("WebP presets", "Text"), WEBP_PRESET_TEXT);

    filterType->addItem(i18nc("WebP filters", "Simple"), 0);
    filterType->addItem(i18nc("WebP filters", "Strong"), 1);

    alphaCompression->addItem(i18nc("WebP alpha plane compression", "None"), 0);
    alphaCompression->addItem(i18nc("WebP alpha plane compression", "Lossless"),
                              1);

    preprocessing->addItem(i18nc("WebP preprocessing filters", "None"), 0);
    preprocessing->addItem(
        i18nc("WebP preprocessing filters", "Segment-smooth"),
        1);
    preprocessing->addItem(
        i18nc("WebP preprocessing filters", "Pseudo-random dithering"),
        2);

    targetPSNR->setDisplayUnit(false);
    targetPSNR->setSuffix(" dB");

    metaDataFilters->setModel(&m_filterRegistryModel);

    connect(preset,
            SIGNAL(currentIndexChanged(int)),
            this,
            SLOT(changePreset(void)));
    connect(lossless, SIGNAL(toggled(bool)), this, SLOT(changePreset(void)));
}

void KisWdgOptionsWebP::setConfiguration(const KisPropertiesConfigurationSP cfg)
{
    haveAnimation->setChecked(cfg->getBool("haveAnimation", true));

    preset->setCurrentIndex(cfg->getInt("preset", 0));
    lossless->setChecked(cfg->getBool("lossless", true));
    quality->setValue(cfg->getDouble("quality", 75.0));
    KisSpinBoxI18nHelper::setText(quality, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
    tradeoff->setValue(cfg->getInt("method", 4));
    dithering->setChecked(cfg->getBool("dithering", true));
    chkForceSRGB->setChecked(cfg->getBool("force_srgb", false));
    chkSaveProfile->setChecked(cfg->getBool("save_profile", true));

    targetSize->setValue(cfg->getInt("target_size", 0));
    targetPSNR->setValue(cfg->getDouble("target_PSNR", 0.0));
    segments->setValue(cfg->getInt("segments", 4));
    snsStrength->setValue(cfg->getInt("sns_strength", 50));
    KisSpinBoxI18nHelper::setText(snsStrength, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
    filterStrength->setValue(cfg->getInt("filter_strength", 60));
    KisSpinBoxI18nHelper::setText(filterStrength, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
    filterSharpness->setValue(cfg->getInt("filter_sharpness", 0));
    filterType->setCurrentIndex(cfg->getInt("filter_type", 1));
    autofilter->setChecked(cfg->getBool("autofilter", false));
    alphaCompression->setCurrentIndex(cfg->getInt("alpha_compression", 1));
    alphaFiltering->setValue(cfg->getInt("alpha_filtering", 1));
    alphaQuality->setValue(cfg->getInt("alpha_quality", 100));
    KisSpinBoxI18nHelper::setText(alphaQuality, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
    pass->setValue(cfg->getInt("pass", 1));
    showCompressed->setChecked(cfg->getBool("show_compressed", false));
    preprocessing->setCurrentIndex(cfg->getInt("preprocessing", 0));
    partitions->setValue(cfg->getInt("partitions", 0));
    partitionLimit->setValue(cfg->getInt("partition_limit", 0));
    KisSpinBoxI18nHelper::setText(partitionLimit, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
    emulateJPEGSize->setChecked(cfg->getBool("emulate_jpeg_size", false));
    threadLevel->setChecked(cfg->getBool("thread_level", false));
    lowMemory->setChecked(cfg->getBool("low_memory", false));
    nearLossless->setValue(cfg->getInt("near_lossless", 100));
    KisSpinBoxI18nHelper::setText(nearLossless, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
    exact->setChecked(cfg->getBool("exact", false));
    useSharpYUV->setChecked(cfg->getBool("use_sharp_yuv", false));
#if WEBP_ENCODER_ABI_VERSION >= 0x020f
    qMin->setValue(cfg->getInt("qmin", 0));
    KisSpinBoxI18nHelper::setText(qMin, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
    qMax->setValue(cfg->getInt("qmax", 100));
    KisSpinBoxI18nHelper::setText(qMax, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
#endif

    exif->setChecked(cfg->getBool("exif", true));
    xmp->setChecked(cfg->getBool("xmp", true));
    chkMetadata->setChecked(cfg->getBool("storeMetaData", true));
    m_filterRegistryModel.setEnabledFilters(
        cfg->getString("filters").split(','));
}

void KisWdgOptionsWebP::changePreset()
{
    WebPConfig preset;

    if (!WebPConfigPreset(
            &preset,
            static_cast<WebPPreset>(this->preset->currentData().value<int>()),
            static_cast<float>(this->quality->value()))) {
        return;
    }

    if (this->lossless->isChecked()
        && !WebPConfigLosslessPreset(&preset, this->tradeoff->value())) {
        return;
    }

    quality->setValue(static_cast<double>(preset.quality));
    tradeoff->setValue(preset.method);

    targetSize->setValue(preset.target_size);
    targetPSNR->setValue(static_cast<double>(preset.target_PSNR));
    segments->setValue(preset.segments);
    snsStrength->setValue(preset.sns_strength);
    filterStrength->setValue(preset.filter_strength);
    filterSharpness->setValue(preset.filter_sharpness);
    filterType->setCurrentIndex(preset.filter_type);
    autofilter->setChecked(preset.autofilter == 1);
    alphaCompression->setCurrentIndex(
        alphaCompression->findData(preset.alpha_compression));
    alphaFiltering->setValue(preset.alpha_filtering);
    alphaQuality->setValue(preset.alpha_quality);
    pass->setValue(preset.pass);
    showCompressed->setChecked(preset.show_compressed == 1);
    preprocessing->setCurrentIndex(
        preprocessing->findData(preset.preprocessing));
    partitions->setValue(preset.partitions);
    partitionLimit->setValue(preset.partition_limit);
    emulateJPEGSize->setChecked(preset.emulate_jpeg_size == 1);
    threadLevel->setChecked(preset.thread_level > 0);
    lowMemory->setChecked(preset.low_memory == 1);
    nearLossless->setValue(preset.near_lossless);
    exact->setChecked(preset.exact == 1);
    useSharpYUV->setChecked(preset.use_sharp_yuv);
#if WEBP_ENCODER_ABI_VERSION >= 0x020f
    qMin->setValue(preset.qmin);
    qMax->setValue(preset.qmax);
#endif
}

KisPropertiesConfigurationSP KisWdgOptionsWebP::configuration() const
{
    KisPropertiesConfigurationSP cfg(new KisPropertiesConfiguration());

    cfg->setProperty("haveAnimation", haveAnimation->isChecked());

    cfg->setProperty("preset", preset->currentIndex());
    cfg->setProperty("lossless", lossless->isChecked());
    cfg->setProperty("quality", quality->value());
    cfg->setProperty("method", tradeoff->value());
    cfg->setProperty("dithering", dithering->isChecked());
    cfg->setProperty("force_srgb", chkForceSRGB->isChecked());
    cfg->setProperty("save_profile", chkSaveProfile->isChecked());

    cfg->setProperty("target_size", targetSize->value());
    cfg->setProperty("target_PSNR", targetPSNR->value());
    cfg->setProperty("segments", segments->value());
    cfg->setProperty("sns_strength", snsStrength->value());
    cfg->setProperty("filter_strength", filterStrength->value());
    cfg->setProperty("filter_sharpness", filterSharpness->value());
    cfg->setProperty("filter_type", filterType->currentData().value<int>());
    cfg->setProperty("autofilter", autofilter->isChecked());
    cfg->setProperty("alpha_compression",
                     alphaCompression->currentData().value<int>());
    cfg->setProperty("alpha_filtering", alphaFiltering->value());
    cfg->setProperty("alpha_quality", alphaQuality->value());
    cfg->setProperty("pass", pass->value());
    cfg->setProperty("show_compressed", showCompressed->isChecked());
    cfg->setProperty("preprocessing",
                     preprocessing->currentData().value<int>());
    cfg->setProperty("partitions", partitions->value());
    cfg->setProperty("partition_limit", partitionLimit->value());
    cfg->setProperty("emulate_jpeg_size", emulateJPEGSize->isChecked());
    cfg->setProperty("thread_level", threadLevel->isChecked());
    cfg->setProperty("low_memory", lowMemory->isChecked());
    cfg->setProperty("near_lossless", nearLossless->value());
    cfg->setProperty("exact", exact->isChecked());
    cfg->setProperty("use_sharp_yuv", useSharpYUV->isChecked());
#if WEBP_ENCODER_ABI_VERSION >= 0x020f
    cfg->setProperty("qmin", qMin->value());
    cfg->setProperty("qmax", qMax->value());
#endif

    cfg->setProperty("exif", exif->isChecked());
    cfg->setProperty("xmp", xmp->isChecked());
    cfg->setProperty("storeMetaData", chkMetadata->isChecked());

    QString enabledFilters;
    for (const KisMetaData::Filter *filter :
         m_filterRegistryModel.enabledFilters()) {
        enabledFilters += filter->id() + ',';
    }
    cfg->setProperty("filters", enabledFilters);

    return cfg;
}
