/*
 *   This file is part of Dianara
 *   Copyright 2012-2019  JanKusanagi JRR <jancoding@gmx.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 of the License, 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.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .
 */

#include "configdialog.h"

ConfigDialog::ConfigDialog(GlobalObject *globalObject,
                           QString dataDirectory, int updateInterval,
                           int tabsPosition, bool tabsMovable,
                           FDNotifications *notifier,
                           QWidget *parent) : QWidget(parent)
{
    m_globalObject = globalObject;
    m_fdNotifier = notifier;

    this->setWindowTitle(tr("Program Configuration")
                         + QStringLiteral(" - Dianara"));
    this->setWindowIcon(QIcon::fromTheme("configure",
                                         QIcon(":/images/button-configure.png")));
    this->setWindowFlags(Qt::Dialog);
    this->setWindowModality(Qt::ApplicationModal);
    this->setMinimumSize(640, 520);

    QSettings settings;
    QSize savedWindowsize = settings.value("ConfigDialog/configWindowSize")
                                    .toSize();
    if (savedWindowsize.isValid())
    {
        this->resize(savedWindowsize);
    }


    settings.beginGroup("Configuration");

    // Standalone Proxy config window
    QByteArray proxyPasswd = QByteArray::fromBase64(settings.value("proxyPassword")
                                                            .toByteArray());
    m_proxyDialog = new ProxyDialog(settings.value("proxyType", 0).toInt(),
                                    settings.value("proxyHostname").toString(),
                                    settings.value("proxyPort").toString(),
                                    settings.value("proxyUseAuth", false).toBool(),
                                    settings.value("proxyUser").toString(),
                                    QString::fromLocal8Bit(proxyPasswd),
                                    this);


    //////////////////////////////////////////////////////////////// Upper part

    // Page 1, general options
    this->createGeneralPage(updateInterval, tabsPosition, tabsMovable);

    // Page 2, fonts
    this->createFontsPage();

    // Page 3, colors
    this->createColorsPage();

    // Page 4, timelines options
    this->createTimelinesPage();

    // Page 5, posts options
    this->createPostsPage();

    // Page 6, composer options
    this->createComposerPage();

    // Page 7, privacy options
    this->createPrivacyPage();

    // Page 8, notifications options
    this->createNotificationsPage(&settings);

    // Page 9, systray options
    this->createSystrayPage();


    settings.endGroup();


    ///////////////////////////////////// List of categories and stacked widget
    m_categoriesListWidget = new QListWidget(this);
    m_categoriesListWidget->setSizePolicy(QSizePolicy::Preferred,
                                          QSizePolicy::MinimumExpanding);
    m_categoriesListWidget->setMinimumWidth(140); // kinda TMP/FIXME
#if 0 // Enable for large-icon-mode with text below
    m_categoriesListWidget->setViewMode(QListView::IconMode);
    m_categoriesListWidget->setFlow(QListView::TopToBottom);
    m_categoriesListWidget->setIconSize(QSize(48, 48));
    m_categoriesListWidget->setWrapping(false);
    m_categoriesListWidget->setMovement(QListView::Static);
#endif
    m_categoriesListWidget->setIconSize(QSize(32, 32));
    m_categoriesListWidget->setUniformItemSizes(true);
    m_categoriesListWidget->setWordWrap(true);
    m_categoriesListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    m_categoriesListWidget->addItem(tr("General Options"));
    m_categoriesListWidget->item(0)
                          ->setIcon(QIcon::fromTheme("preferences-other",
                                                     QIcon(":/images/button-configure.png")));
    m_categoriesListWidget->addItem(tr("Fonts"));
    m_categoriesListWidget->item(1)
                          ->setIcon(QIcon::fromTheme("preferences-desktop-font",
                                                     QIcon(":/images/button-configure.png")));
    m_categoriesListWidget->addItem(tr("Colors"));
    m_categoriesListWidget->item(2)
                          ->setIcon(QIcon::fromTheme("preferences-desktop-color",
                                                     QIcon(":/images/button-configure.png")));
    m_categoriesListWidget->addItem(tr("Timelines"));
    m_categoriesListWidget->item(3)
                          ->setIcon(QIcon::fromTheme("view-list-details",
                                                     QIcon(":/images/feed-inbox.png")));
    m_categoriesListWidget->addItem(tr("Posts"));
    m_categoriesListWidget->item(4)
                          ->setIcon(QIcon::fromTheme("mail-message",
                                                     QIcon(":/images/button-post.png")));
    m_categoriesListWidget->addItem(tr("Composer"));
    m_categoriesListWidget->item(5)
                          ->setIcon(QIcon::fromTheme("document-edit",
                                                     QIcon(":/images/button-edit.png")));
    m_categoriesListWidget->addItem(tr("Privacy"));
    m_categoriesListWidget->item(6)
                          ->setIcon(QIcon::fromTheme("object-locked",
                                                     QIcon(":/images/button-password.png")));
    m_categoriesListWidget->addItem(tr("Notifications"));
    m_categoriesListWidget->item(7)
                          ->setIcon(QIcon::fromTheme("preferences-desktop-notification",
                                                     QIcon(":/images/button-online.png")));
    m_categoriesListWidget->addItem(tr("System Tray"));     // dashboard-show ?
    m_categoriesListWidget->item(8)
                          ->setIcon(QIcon::fromTheme("configure-toolbars",
                                                     QIcon(":/images/button-configure.png")));

    m_categoriesStackedWidget = new QStackedWidget(this);
    m_categoriesStackedWidget->setSizePolicy(QSizePolicy::Preferred,
                                             QSizePolicy::MinimumExpanding);
    m_categoriesStackedWidget->addWidget(m_generalOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_fontOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_colorOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_timelinesOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_postsOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_composerOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_privacyOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_notifOptionsWidget);
    m_categoriesStackedWidget->addWidget(m_systrayOptionsWidget);

    connect(m_categoriesListWidget, &QListWidget::currentRowChanged,
            m_categoriesStackedWidget, &QStackedWidget::setCurrentIndex);

    m_topLayout = new QHBoxLayout();
    m_topLayout->addWidget(m_categoriesListWidget);
    m_topLayout->addWidget(m_categoriesStackedWidget);



    /////////////////////////////////////////////////////////////// Bottom part

    // Label to show where the data directory is
    m_dataDirectoryLabel = new QLabel(tr("Dianara stores data in this folder:")
                                      + QString(" <a href=\"%1\">%2</a>")
                                        .arg(dataDirectory).arg(dataDirectory),
                                      this);
    m_dataDirectoryLabel->setWordWrap(true);
    m_dataDirectoryLabel->setOpenExternalLinks(true);


    // Save / Cancel buttons
    m_saveConfigButton = new QPushButton(QIcon::fromTheme("document-save",
                                                          QIcon(":/images/button-save.png")),
                                         tr("&Save Configuration"),
                                         this);
    connect(m_saveConfigButton, &QAbstractButton::clicked,
            this, &ConfigDialog::saveConfiguration);

    m_cancelButton = new QPushButton(QIcon::fromTheme("dialog-cancel",
                                                      QIcon(":/images/button-cancel.png")),
                                     tr("&Cancel"),
                                     this);
    connect(m_cancelButton, &QAbstractButton::clicked,
            this, &QWidget::hide);

    m_buttonBox = new QDialogButtonBox(this);
    m_buttonBox->addButton(m_saveConfigButton, QDialogButtonBox::AcceptRole);
    m_buttonBox->addButton(m_cancelButton, QDialogButtonBox::RejectRole);


    // ESC to close
    m_closeAction = new QAction(this);
    m_closeAction->setShortcut(QKeySequence(Qt::Key_Escape));
    connect(m_closeAction, &QAction::triggered,
            this, &QWidget::hide);
    this->addAction(m_closeAction);



    //// Set up main layout
    m_mainLayout = new QVBoxLayout();
    m_mainLayout->addLayout(m_topLayout, 20);
    m_mainLayout->addSpacing(8);
    m_mainLayout->addStretch(1);
    m_mainLayout->addWidget(m_dataDirectoryLabel);
    m_mainLayout->addSpacing(8);
    m_mainLayout->addStretch(2);
    m_mainLayout->addWidget(m_buttonBox);
    this->setLayout(m_mainLayout);

    // Activate the first category (so the row already looks selected)
    m_categoriesListWidget->setCurrentRow(0);
    m_categoriesListWidget->setFocus();

    qDebug() << "Config dialog created";
}

ConfigDialog::~ConfigDialog()
{
    qDebug() << "Config dialog destroyed";
}


/*
 * Page 1, general options
 *
 */
void ConfigDialog::createGeneralPage(int updateInterval,
                                     int tabsPosition, bool tabsMovable)
{
    m_updateIntervalSpinbox = new QSpinBox(this);
    m_updateIntervalSpinbox->setRange(2, 99); // 2-99 min
    m_updateIntervalSpinbox->setSuffix(" " + tr("minutes"));
    m_updateIntervalSpinbox->setValue(updateInterval);


    m_tabsPositionCombobox = new QComboBox(this);
    m_tabsPositionCombobox->addItem(QIcon::fromTheme("arrow-up"),
                                    tr("Top"));
    m_tabsPositionCombobox->addItem(QIcon::fromTheme("arrow-down"),
                                    tr("Bottom"));
    m_tabsPositionCombobox->addItem(QIcon::fromTheme("arrow-left"),
                                    tr("Left side",
                                       "tabs on left side/west; RTL not affected"));
    m_tabsPositionCombobox->addItem(QIcon::fromTheme("arrow-right"),
                                    tr("Right side",
                                       "tabs on right side/east; RTL not affected"));
    m_tabsPositionCombobox->setCurrentIndex(tabsPosition);

    m_tabsMovableCheckbox = new QCheckBox(this);
    m_tabsMovableCheckbox->setChecked(tabsMovable);


    m_proxyButton = new QPushButton(QIcon::fromTheme("preferences-system-network",
                                                     QIcon(":/images/button-configure.png")),
                                    tr("Pro&xy Settings"),
                                    this);
    connect(m_proxyButton, &QAbstractButton::clicked,
            m_proxyDialog, &QWidget::show);

    m_filterEditorButton = new QPushButton(QIcon::fromTheme("view-filter",
                                                            QIcon(":/images/button-filter.png")),
                                           tr("Set Up F&ilters"),
                                           this);
    connect(m_filterEditorButton, &QAbstractButton::clicked,
            this, &ConfigDialog::filterEditorRequested);


    QFrame *lineFrame1 = new QFrame(this); // ----------------------------
    lineFrame1->setFrameStyle(QFrame::HLine);

    QFrame *lineFrame2 = new QFrame(this); // ----------------------------
    lineFrame2->setFrameStyle(QFrame::HLine);


    m_generalOptionsLayout = new QFormLayout();
    m_generalOptionsLayout->addRow(tr("Timeline &update interval"),
                                   m_updateIntervalSpinbox);
    m_generalOptionsLayout->addRow(lineFrame1);
    m_generalOptionsLayout->addRow(tr("&Tabs position"),
                                   m_tabsPositionCombobox);
    m_generalOptionsLayout->addRow(tr("&Movable tabs"),
                                   m_tabsMovableCheckbox);
    m_generalOptionsLayout->addRow(lineFrame2);
    m_generalOptionsLayout->addRow(tr("Network configuration"),
                                   m_proxyButton);
    m_generalOptionsLayout->addRow(tr("Filtering rules"),
                                   m_filterEditorButton);

    m_generalOptionsWidget = new QWidget(this);
    m_generalOptionsWidget->setLayout(m_generalOptionsLayout);
}


/*
 * Page 2, fonts
 *
 */
void ConfigDialog::createFontsPage()
{
    m_fontPicker1 = new FontPicker(tr("Post Titles"),
                                   m_globalObject->getPostTitleFont(),
                                   this);
    m_fontPicker2 = new FontPicker(tr("Post Contents"),
                                   m_globalObject->getPostContentsFont(),
                                   this);
    m_fontPicker3 = new FontPicker(tr("Comments"),
                                   m_globalObject->getCommentsFont(),
                                   this);
    m_fontPicker4 = new FontPicker(tr("Minor Feeds"),
                                   m_globalObject->getMinorFeedFont(),
                                   this);
    // FIXME: more for "Timestamps" or something else?
    // FIXME: add a "base font size" option


    m_fontOptionsLayout = new QVBoxLayout();
    m_fontOptionsLayout->addWidget(m_fontPicker1);
    m_fontOptionsLayout->addWidget(m_fontPicker2);
    m_fontOptionsLayout->addWidget(m_fontPicker3);
    m_fontOptionsLayout->addWidget(m_fontPicker4);
    m_fontOptionsLayout->addStretch(1);

    m_fontOptionsWidget = new QWidget(this);
    m_fontOptionsWidget->setLayout(m_fontOptionsLayout);
}


/*
 * Page 3, colors
 *
 */
void ConfigDialog::createColorsPage()
{
    m_colorPicker1 = new ColorPicker(tr("You are among the recipients "
                                        "of the activity, such as "
                                        "a comment addressed to you.")
                                     + "\n"
                                     + tr("Used also when highlighting posts "
                                          "addressed to you in the timelines."),
                                     m_globalObject->getColor(0),
                                     this);

    m_colorPicker2 = new ColorPicker(tr("The activity is in reply to something "
                                        "done by you, such as a comment posted "
                                        "in reply to one of your notes."),
                                     m_globalObject->getColor(1),
                                     this);

    m_colorPicker3 = new ColorPicker(tr("You are the object of the activity, "
                                        "such as someone adding you to a list."),
                                     m_globalObject->getColor(2),
                                     this);

    m_colorPicker4 = new ColorPicker(tr("The activity is related to one of "
                                        "your objects, such as someone "
                                        "liking one of your posts.")
                                     + "\n"
                                     + tr("Used also when highlighting your "
                                          "own posts in the timelines."),
                                     m_globalObject->getColor(3),
                                     this);

    m_colorPicker5 = new ColorPicker(tr("Item highlighted due to filtering "
                                        "rules."),
                                     m_globalObject->getColor(4),
                                     this);

    m_colorPicker6 = new ColorPicker(tr("Item is new."),
                                     m_globalObject->getColor(5),
                                     this);


    m_colorOptionsLayout = new QVBoxLayout();
    m_colorOptionsLayout->addWidget(m_colorPicker1);
    m_colorOptionsLayout->addWidget(m_colorPicker2);
    m_colorOptionsLayout->addWidget(m_colorPicker3);
    m_colorOptionsLayout->addWidget(m_colorPicker4);
    m_colorOptionsLayout->addWidget(m_colorPicker5);
    m_colorOptionsLayout->addWidget(m_colorPicker6);

    m_colorOptionsWidget = new QWidget(this);
    m_colorOptionsWidget->setLayout(m_colorOptionsLayout);
}


/*
 * Page 4, timelines options
 *
 */
void ConfigDialog::createTimelinesPage()
{
    m_postsPerPageMainSpinbox = new QSpinBox(this);
    m_postsPerPageMainSpinbox->setRange(5, 50); // 5-50 ppp
    m_postsPerPageMainSpinbox->setSuffix(" " + tr("posts",
                                                  "This goes after a number, "
                                                  "like: 10 posts"));
    m_postsPerPageMainSpinbox->setValue(m_globalObject->getPostsPerPageMain());

    m_postsPerPageOtherSpinbox = new QSpinBox(this);
    m_postsPerPageOtherSpinbox->setRange(1, 30); // 1-30 ppp
    m_postsPerPageOtherSpinbox->setSuffix(" " + tr("posts", // Identical to previous
                                                   "This goes after a number, "
                                                   "like: 10 posts"));
    m_postsPerPageOtherSpinbox->setValue(m_globalObject->getPostsPerPageOther());

    m_showDeletedCheckbox = new QCheckBox(this);
    m_showDeletedCheckbox->setChecked(m_globalObject->getShowDeleted());

    m_hideDuplicatesCheckbox = new QCheckBox(this);
    m_hideDuplicatesCheckbox->setChecked(m_globalObject->getHideDuplicates());

    m_jumpToNewCheckbox = new QCheckBox(this);
    m_jumpToNewCheckbox->setChecked(m_globalObject->getJumpToNewOnUpdate());


    m_mfSnippetsCombobox = new QComboBox(this);
    m_mfSnippetsCombobox->addItem(tr("Highlighted activities, except mine"));
    m_mfSnippetsCombobox->addItem(tr("Any highlighted activity"));
    m_mfSnippetsCombobox->addItem(tr("Always"));
    m_mfSnippetsCombobox->addItem(tr("Never"));
    m_mfSnippetsCombobox->setCurrentIndex(m_globalObject->getMinorFeedSnippetsType());

    m_snippetLimitSpinbox = new QSpinBox(this);
    m_snippetLimitSpinbox->setRange(10, 10000);
    m_snippetLimitSpinbox->setSuffix(" " + tr("characters",
                                              "This is a suffix, after a number"));
    m_snippetLimitSpinbox->setValue(m_globalObject->getSnippetsCharLimit());

    m_snippetLimitHlSpinbox = new QSpinBox(this);
    m_snippetLimitHlSpinbox->setRange(5, 10000);
    m_snippetLimitHlSpinbox->setSuffix(m_snippetLimitSpinbox->suffix());
    m_snippetLimitHlSpinbox->setValue(m_globalObject->getSnippetsCharLimitHl());

    m_mfAvatarSizeCombobox = this->newAvatarComboBox();
    m_mfAvatarSizeCombobox->setCurrentIndex(m_globalObject->getMfAvatarIndex());

    m_mfIconTypeCombobox = new QComboBox(this);
    m_mfIconTypeCombobox->addItem(tr("No"));
    m_mfIconTypeCombobox->addItem(tr("Before avatar"));
    m_mfIconTypeCombobox->addItem(tr("Before avatar, subtle"));
    m_mfIconTypeCombobox->addItem(tr("After avatar"));
    m_mfIconTypeCombobox->addItem(tr("After avatar, subtle"));
    m_mfIconTypeCombobox->setCurrentIndex(m_globalObject->getMfIconType());


    // TMP/FIXME, use GroupBoxes instead of a separator
    QFrame *tlLineFrame = new QFrame(this); // -----------------------
    tlLineFrame->setFrameStyle(QFrame::HLine);

    m_timelinesOptionsLayout = new QFormLayout();
    m_timelinesOptionsLayout->addRow(tr("&Posts per page, main timeline"),
                                     m_postsPerPageMainSpinbox);
    m_timelinesOptionsLayout->addRow(tr("Posts per page, &other timelines"),
                                     m_postsPerPageOtherSpinbox);
    m_timelinesOptionsLayout->addRow(tr("Show information for deleted posts"),
                                     m_showDeletedCheckbox);
    m_timelinesOptionsLayout->addRow(tr("Hide duplicated posts"),
                                     m_hideDuplicatesCheckbox);
    m_timelinesOptionsLayout->addRow(tr("Jump to new posts line on update"),
                                     m_jumpToNewCheckbox);
    m_timelinesOptionsLayout->addRow(tlLineFrame);
    m_timelinesOptionsLayout->addRow(tr("Show snippets in minor feeds"),
                                     m_mfSnippetsCombobox);
    m_timelinesOptionsLayout->addRow(tr("Snippet limit"),
                                     m_snippetLimitSpinbox);
    m_timelinesOptionsLayout->addRow(tr("Snippet limit when highlighted"),
                                     m_snippetLimitHlSpinbox);
    m_timelinesOptionsLayout->addRow(tr("Minor feed avatar sizes"),  // TMP string -- FIXME
                                     m_mfAvatarSizeCombobox);
    m_timelinesOptionsLayout->addRow(tr("Show activity icons"),
                                     m_mfIconTypeCombobox);

    m_timelinesOptionsWidget = new QWidget(this);
    m_timelinesOptionsWidget->setLayout(m_timelinesOptionsLayout);
}


/*
 * Page 5, posts options
 *
 */
void ConfigDialog::createPostsPage()
{
    m_postAvatarSizeCombobox = this->newAvatarComboBox();
    m_postAvatarSizeCombobox->setCurrentIndex(m_globalObject->getPostAvatarIndex());

    m_commentAvatarSizeCombobox = this->newAvatarComboBox();
    m_commentAvatarSizeCombobox->setCurrentIndex(m_globalObject->getCommentAvatarIndex());

    m_showExtendedSharesCheckbox = new QCheckBox(this);
    m_showExtendedSharesCheckbox->setChecked(m_globalObject->getPostExtendedShares());

    m_showExtraInfoCheckbox = new QCheckBox(this);
    m_showExtraInfoCheckbox->setChecked(m_globalObject->getPostShowExtraInfo());

    m_postHlAuthorCommentsCheckbox = new QCheckBox(this);
    m_postHlAuthorCommentsCheckbox->setChecked(m_globalObject->getPostHLAuthorComments());

    m_postHLOwnCommentsCheckbox = new QCheckBox(this);
    m_postHLOwnCommentsCheckbox->setChecked(m_globalObject->getPostHLOwnComments());

    m_postIgnoreSslInImages = new QCheckBox(tr("Only for images inserted from "
                                               "web sites.")
                                            + "\n"
                                            + tr("Use with care."),
                                            this);
    m_postIgnoreSslInImages->setChecked(m_globalObject->getPostIgnoreSslInImages());

    m_postFullImagesCheckbox = new QCheckBox(this);
    m_postFullImagesCheckbox->setChecked(m_globalObject->getPostFullImages());


    m_postsOptionsLayout = new QFormLayout();
    m_postsOptionsLayout->addRow(tr("Avatar size"),
                                 m_postAvatarSizeCombobox);
    m_postsOptionsLayout->addRow(tr("Avatar size in comments"),
                                 m_commentAvatarSizeCombobox);
    m_postsOptionsLayout->addRow(tr("Show extended share information"),
                                 m_showExtendedSharesCheckbox);
    m_postsOptionsLayout->addRow(tr("Show extra information"),
                                 m_showExtraInfoCheckbox);
    m_postsOptionsLayout->addRow(tr("Highlight post author's comments"),
                                 m_postHlAuthorCommentsCheckbox);
    m_postsOptionsLayout->addRow(tr("Highlight your own comments"),
                                 m_postHLOwnCommentsCheckbox);
    m_postsOptionsLayout->addRow(tr("Ignore SSL errors in images"),
                                 m_postIgnoreSslInImages);
    m_postsOptionsLayout->addRow(tr("Show full size images"),
                                 m_postFullImagesCheckbox);

    m_postsOptionsWidget = new QWidget(this);
    m_postsOptionsWidget->setLayout(m_postsOptionsLayout);
}


/*
 * Page 6, composer options
 *
 */
void ConfigDialog::createComposerPage()
{
    m_publicPostsCheckbox = new QCheckBox(this);
    m_publicPostsCheckbox->setChecked(m_globalObject->getPublicPostsByDefault());

    m_useFilenameAsTitleCheckbox = new QCheckBox(this);
    m_useFilenameAsTitleCheckbox->setChecked(m_globalObject->getUseFilenameAsTitle());

    m_showCharacterCounterCheckbox = new QCheckBox(this);
    m_showCharacterCounterCheckbox->setChecked(m_globalObject->getShowCharacterCounter());


    m_composerOptionsLayout = new QFormLayout();
    m_composerOptionsLayout->addRow(tr("Public posts as &default"),
                                    m_publicPostsCheckbox);
    m_composerOptionsLayout->addRow(tr("Use attachment filename as initial "
                                       "post title"),
                                    m_useFilenameAsTitleCheckbox);
    m_composerOptionsLayout->addRow(tr("Show character counter"),
                                    m_showCharacterCounterCheckbox);

    m_composerOptionsWidget = new QWidget(this);
    m_composerOptionsWidget->setLayout(m_composerOptionsLayout);
}


/*
 * Page 7, privacy options
 *
 */
void ConfigDialog::createPrivacyPage()
{
    m_silentFollowsCheckbox = new QCheckBox(this);
    m_silentFollowsCheckbox->setChecked(m_globalObject->getSilentFollows());

    m_silentListsCheckbox = new QCheckBox(this);
    m_silentListsCheckbox->setChecked(m_globalObject->getSilentLists());

    m_silentLikesCheckbox = new QCheckBox(this);
    m_silentLikesCheckbox->setChecked(m_globalObject->getSilentLikes());


    m_privacyOptionsLayout = new QFormLayout();
    m_privacyOptionsLayout->addRow(tr("Don't inform followers when "
                                      "following someone"),
                                   m_silentFollowsCheckbox);
    m_privacyOptionsLayout->addRow(tr("Don't inform followers when "
                                      "handling lists"),
                                   m_silentListsCheckbox);
    m_privacyOptionsLayout->addRow(tr("Inform only the author when "
                                      "liking things"),
                                   m_silentLikesCheckbox);

    m_privacyOptionsWidget = new QWidget(this);
    m_privacyOptionsWidget->setLayout(m_privacyOptionsLayout);
}


/*
 * Page 8, notifications options
 *
 */
void ConfigDialog::createNotificationsPage(QSettings *settings)
{
    m_notifStyleCombobox = new QComboBox(this);
    m_notifStyleCombobox->addItem(QIcon::fromTheme("preferences-desktop-notification"),
                                  tr("As system notifications"));
    m_notifStyleCombobox->addItem(QIcon::fromTheme("view-conversation-balloon"),
                                  tr("Using own notifications"));
    m_notifStyleCombobox->addItem(QIcon::fromTheme("user-busy"), // dialog-cancel
                                  tr("Don't show notifications"));
    m_notifStyleCombobox->setCurrentIndex(settings->value("showNotifications",
                                                          0).toInt());
    // Keeping these connects old-style due to overload
    connect(m_notifStyleCombobox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(toggleNotificationDetails(int)));
    // Check FD.org notifications availability when selecting an option
    connect(m_notifStyleCombobox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(showDemoNotification(int)));

    m_notifStatusLabel = new QLabel(this);

    m_notifDurationSpinbox = new QSpinBox(this);
    m_notifDurationSpinbox->setRange(1, 60);
    m_notifDurationSpinbox->setSuffix(" " + tr("seconds",
                                               "Next to a duration, in seconds"));
    m_notifDurationSpinbox->setValue(settings->value("notificationDuration",
                                                     4).toInt()); // 4s default

    m_notifPersistentCheckbox = new QCheckBox(this);
    connect(m_notifPersistentCheckbox, &QAbstractButton::toggled,
            m_notifDurationSpinbox, &QWidget::setDisabled);
    m_notifPersistentCheckbox->setChecked(settings->value("notificationPersistent",
                                                          false).toBool());

    m_notifTaskbarCheckbox = new QCheckBox(this);
    m_notifTaskbarCheckbox->setChecked(m_globalObject->getNotifyInTaskbar());


    m_notifyNewTLCheckbox = new QCheckBox(this);
    m_notifyNewTLCheckbox->setChecked(settings->value("notifyNewTL",
                                                      false).toBool());
    m_notifyHLTLCheckbox = new QCheckBox(this);
    m_notifyHLTLCheckbox->setChecked(settings->value("notifyHLTL",
                                                     true).toBool());
    m_notifyNewMWCheckbox = new QCheckBox(this);
    m_notifyNewMWCheckbox->setChecked(settings->value("notifyNewMW",
                                                      false).toBool());
    m_notifyHLMWCheckbox = new QCheckBox(this);
    m_notifyHLMWCheckbox->setChecked(settings->value("notifyHLMW",
                                                     true).toBool());
    m_notifyErrorsCheckbox = new QCheckBox(this);
    m_notifyErrorsCheckbox->setChecked(settings->value("notifyErrors",
                                                       true).toBool());

    this->syncNotifierOptions();

    // Initial check to see if currently selected style is available
    this->checkNotifications(m_notifStyleCombobox->currentIndex());


    m_notifOptionsLayout = new QFormLayout();
    m_notifOptionsLayout->addRow(tr("Notification Style"),
                                 m_notifStyleCombobox);
    m_notifOptionsLayout->addRow(QString(), // Empty label on left to align with right column
                                 m_notifStatusLabel);
    m_notifOptionsLayout->addRow(tr("Duration"),
                                 m_notifDurationSpinbox);
    m_notifOptionsLayout->addRow(tr("Persistent Notifications"),
                                 m_notifPersistentCheckbox);
    m_notifOptionsLayout->addRow(tr("Also highlight taskbar entry"),
                                 m_notifTaskbarCheckbox);


    m_notifOptionsLayout->addRow(new QLabel("<br />" // TMP/FIXME: put these options
                                            "<b>"    //            inside a GroupBox?
                                            + tr("Notify when receiving:")
                                            + "</b>"
                                              "<br />",
                                            this));
    m_notifOptionsLayout->addRow(tr("New posts"),
                                 m_notifyNewTLCheckbox);
    m_notifOptionsLayout->addRow(tr("Highlighted posts"),
                                 m_notifyHLTLCheckbox);
    m_notifOptionsLayout->addRow(tr("New activities in minor feed"),
                                 m_notifyNewMWCheckbox);
    m_notifOptionsLayout->addRow(tr("Highlighted activities in minor feed"),
                                 m_notifyHLMWCheckbox);
    m_notifOptionsLayout->addRow(tr("Important errors"),
                                 m_notifyErrorsCheckbox);

    m_notifOptionsWidget = new QWidget(this);
    m_notifOptionsWidget->setLayout(m_notifOptionsLayout);
}


/*
 * Page 9, systray options
 *
 */
void ConfigDialog::createSystrayPage()
{
    m_systrayIconTypeCombobox = new QComboBox(this);
    m_systrayIconTypeCombobox->addItem(tr("Default"));
    m_systrayIconTypeCombobox->addItem(tr("System iconset, if available"));
    m_systrayIconTypeCombobox->addItem(tr("Show your current avatar"));
    m_systrayIconTypeCombobox->addItem(tr("Custom icon"));
    m_systrayIconTypeCombobox->setCurrentIndex(m_globalObject->getTrayIconType());
    // connect kept old-style
    connect(m_systrayIconTypeCombobox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(toggleCustomIconButton(int)));


    m_systrayCustomIconButton = new QPushButton(tr("S&elect..."), this);
    m_systrayIconLastDir = QDir::homePath();
    m_systrayCustomIconFN = m_globalObject->getTrayIconFilename();
    // FIXME: merge this with code used in pickCustomIconFile()
    // and turn the warning messageBox into a label
    if (!QPixmap(m_systrayCustomIconFN).isNull())
    {
        m_systrayCustomIconButton->setIcon(QIcon(m_systrayCustomIconFN));
        m_systrayCustomIconButton->setToolTip("<b></b>"
                                              + m_systrayCustomIconFN);
    }
    else
    {
        m_systrayCustomIconButton->setIcon(QIcon(":/icon/32x32/dianara.png"));
    }
    connect(m_systrayCustomIconButton, &QAbstractButton::clicked,
            this, &ConfigDialog::pickCustomIconFile);

    // Enable/disable initially based on loaded config
    this->toggleCustomIconButton(m_systrayIconTypeCombobox->currentIndex());


    m_systrayHideCheckbox = new QCheckBox(this);
    m_systrayHideCheckbox->setChecked(m_globalObject->getTrayHideOnStartup());


    m_systrayOptionsLayout = new QFormLayout();
    m_systrayOptionsLayout->addRow(tr("System Tray Icon &Type"),
                                   m_systrayIconTypeCombobox);
    m_systrayOptionsLayout->addRow(tr("Custom &Icon"),
                                   m_systrayCustomIconButton);
    m_systrayOptionsLayout->addRow(tr("Hide window on startup"),
                                   m_systrayHideCheckbox);

    m_systrayOptionsWidget = new QWidget(this);
    m_systrayOptionsWidget->setLayout(m_systrayOptionsLayout);
}


QComboBox *ConfigDialog::newAvatarComboBox()
{
    QComboBox *avatarCombobox = new QComboBox(this);
    avatarCombobox->addItem("16x16");
    avatarCombobox->addItem("32x32");
    avatarCombobox->addItem("48x48");
    avatarCombobox->addItem("64x64");
    avatarCombobox->addItem("96x96");
    avatarCombobox->addItem("128x128");
    avatarCombobox->addItem("256x256");

    return avatarCombobox;
}



void ConfigDialog::syncNotifierOptions()
{
    this->toggleNotificationDetails(m_notifStyleCombobox->currentIndex());

    int notificationDuration = m_notifDurationSpinbox->value();
    if (m_notifPersistentCheckbox->isChecked())
    {
        notificationDuration = 0;
    }

    m_fdNotifier->setNotificationOptions(m_notifStyleCombobox->currentIndex(),
                                         notificationDuration,
                                         m_notifyNewTLCheckbox->isChecked(),
                                         m_notifyHLTLCheckbox->isChecked(),
                                         m_notifyNewMWCheckbox->isChecked(),
                                         m_notifyHLMWCheckbox->isChecked(),
                                         m_notifyErrorsCheckbox->isChecked());
}


/*
 * Get a demo message for the current notification style
 *
 * Show also a warning is system notifications are not available
 *
 */
QString ConfigDialog::checkNotifications(int notificationStyle)
{
    QString demoText;
    if (notificationStyle == FDNotifications::SystemNotifications)
    {
        if (m_fdNotifier->areNotificationsAvailable())
        {
            demoText = tr("This is a system notification");
        }
        else
        {
            demoText = tr("System notifications are not available!")
                       + "<br>"
                       + tr("Own notifications will be used.");

            m_notifStatusLabel->setText("<i>" + demoText + "</i>");
            /* FIXME: Should also check availability of system tray icon,
             *        needed to show Qt's balloon notifications
             */
        }
    }
    else
    {
        demoText = tr("This is a basic notification");
    }

    return demoText;
}


void ConfigDialog::setPublicPosts(bool value)
{
    m_publicPostsCheckbox->setChecked(value);
    this->saveConfiguration(); // This might be overkill -- FIXME TMP
}



//////////////////////////////////////////////////////////////////////////////
///////////////////////////////// SLOTS //////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////



void ConfigDialog::saveConfiguration()
{
    QSettings settings;
    if (!settings.isWritable())
    {
        // TMP FIXME: notify user properly

        qDebug() << "ERROR SAVING CONFIGURATION (maybe disk full?)";
        return;
    }

    settings.beginGroup("Configuration");

    // General
    settings.setValue("updateInterval", m_updateIntervalSpinbox->value());

    settings.setValue("tabsPosition", m_tabsPositionCombobox->currentIndex());
    settings.setValue("tabsMovable",  m_tabsMovableCheckbox->isChecked());


    // Fonts
    settings.setValue("font1", m_fontPicker1->getFontInfo());
    settings.setValue("font2", m_fontPicker2->getFontInfo());
    settings.setValue("font3", m_fontPicker3->getFontInfo());
    settings.setValue("font4", m_fontPicker4->getFontInfo());
    m_globalObject->syncFontSettings(m_fontPicker1->getFontInfo(),
                                     m_fontPicker2->getFontInfo(),
                                     m_fontPicker3->getFontInfo(),
                                     m_fontPicker4->getFontInfo());

    // Colors
    settings.setValue("color1", m_colorPicker1->getCurrentColor());
    settings.setValue("color2", m_colorPicker2->getCurrentColor());
    settings.setValue("color3", m_colorPicker3->getCurrentColor());
    settings.setValue("color4", m_colorPicker4->getCurrentColor());
    settings.setValue("color5", m_colorPicker5->getCurrentColor());
    settings.setValue("color6", m_colorPicker6->getCurrentColor());

    const QStringList highlightColorsList =
                      QStringList{ m_colorPicker1->getCurrentColor(),
                                   m_colorPicker2->getCurrentColor(),
                                   m_colorPicker3->getCurrentColor(),
                                   m_colorPicker4->getCurrentColor(),
                                   m_colorPicker5->getCurrentColor(),
                                   m_colorPicker6->getCurrentColor() };
    m_globalObject->syncColorSettings(highlightColorsList);


    // Timelines
    settings.setValue("postsPerPageMain",
                      m_postsPerPageMainSpinbox->value());
    settings.setValue("postsPerPageOther",
                      m_postsPerPageOtherSpinbox->value());
    settings.setValue("showDeletedPosts",
                      m_showDeletedCheckbox->isChecked());
    settings.setValue("hideDuplicatedPosts",
                      m_hideDuplicatesCheckbox->isChecked());
    settings.setValue("jumpToNewOnUpdate",
                      m_jumpToNewCheckbox->isChecked());
    settings.setValue("mfSnippetsType",
                      m_mfSnippetsCombobox->currentIndex());
    settings.setValue("snippetCharLimit",
                      m_snippetLimitSpinbox->value());
    settings.setValue("snippetCharLimitHl",
                      m_snippetLimitHlSpinbox->value());
    settings.setValue("minorFeedAvatarIndex",
                      m_mfAvatarSizeCombobox->currentIndex());
    settings.setValue("minorFeedIconType",
                      m_mfIconTypeCombobox->currentIndex());

    m_globalObject->syncTimelinesSettings(m_postsPerPageMainSpinbox->value(),
                                          m_postsPerPageOtherSpinbox->value(),
                                          m_showDeletedCheckbox->isChecked(),
                                          m_hideDuplicatesCheckbox->isChecked(),
                                          m_jumpToNewCheckbox->isChecked(),
                                          m_mfSnippetsCombobox->currentIndex(),
                                          m_snippetLimitSpinbox->value(),
                                          m_snippetLimitHlSpinbox->value(),
                                          m_mfAvatarSizeCombobox->currentIndex(),
                                          m_mfIconTypeCombobox->currentIndex());

    // Posts
    settings.setValue("postAvatarIndex",
                      m_postAvatarSizeCombobox->currentIndex());
    settings.setValue("commentAvatarIndex",
                      m_commentAvatarSizeCombobox->currentIndex());
    settings.setValue("postExtendedShares",
                      m_showExtendedSharesCheckbox->isChecked());
    settings.setValue("postShowExtraInfo",
                      m_showExtraInfoCheckbox->isChecked());
    settings.setValue("postHLAuthorComments",
                      m_postHlAuthorCommentsCheckbox->isChecked());
    settings.setValue("postHLOwnComments",
                      m_postHLOwnCommentsCheckbox->isChecked());
    settings.setValue("postIgnoreSslInImages",
                      m_postIgnoreSslInImages->isChecked());
    settings.setValue("postFullImages",
                      m_postFullImagesCheckbox->isChecked());
    m_globalObject->syncPostSettings(m_postAvatarSizeCombobox->currentIndex(),
                                     m_commentAvatarSizeCombobox->currentIndex(),
                                     m_showExtendedSharesCheckbox->isChecked(),
                                     m_showExtraInfoCheckbox->isChecked(),
                                     m_postHlAuthorCommentsCheckbox->isChecked(),
                                     m_postHLOwnCommentsCheckbox->isChecked(),
                                     m_postIgnoreSslInImages->isChecked(),
                                     m_postFullImagesCheckbox->isChecked());


    // Composer
    settings.setValue("publicPosts",
                      m_publicPostsCheckbox->isChecked());
    settings.setValue("useFilenameAsTitle",
                      m_useFilenameAsTitleCheckbox->isChecked());
    settings.setValue("showCharacterCounter",
                      m_showCharacterCounterCheckbox->isChecked());
    m_globalObject->syncComposerSettings(m_publicPostsCheckbox->isChecked(),
                                         m_useFilenameAsTitleCheckbox->isChecked(),
                                         m_showCharacterCounterCheckbox->isChecked());


    // Privacy
    settings.setValue("silentFollows",
                      m_silentFollowsCheckbox->isChecked());
    settings.setValue("silentLists",
                      m_silentListsCheckbox->isChecked());
    settings.setValue("silentLikes",
                      m_silentLikesCheckbox->isChecked());
    m_globalObject->syncPrivacySettings(m_silentFollowsCheckbox->isChecked(),
                                        m_silentListsCheckbox->isChecked(),
                                        m_silentLikesCheckbox->isChecked());


    // Notifications
    settings.setValue("showNotifications",
                      m_notifStyleCombobox->currentIndex());
    settings.setValue("notificationDuration",
                      m_notifDurationSpinbox->value());
    settings.setValue("notificationPersistent",
                      m_notifPersistentCheckbox->isChecked());
    settings.setValue("notificationTaskbar",
                      m_notifTaskbarCheckbox->isChecked());
    settings.setValue("notifyNewTL",  m_notifyNewTLCheckbox->isChecked());
    settings.setValue("notifyHLTL",   m_notifyHLTLCheckbox->isChecked());
    settings.setValue("notifyNewMW",  m_notifyNewMWCheckbox->isChecked());
    settings.setValue("notifyHLMW",   m_notifyHLMWCheckbox->isChecked());
    settings.setValue("notifyErrors", m_notifyErrorsCheckbox->isChecked());
    this->syncNotifierOptions();
    m_globalObject->syncNotificationSettings(m_notifTaskbarCheckbox->isChecked());
                     // FIXME, most still missing


    // Tray
    settings.setValue("systrayIconType", m_systrayIconTypeCombobox->currentIndex());
    settings.setValue("systrayCustomIconFN", m_systrayCustomIconFN);
    settings.setValue("systrayHideInTray", m_systrayHideCheckbox->isChecked());
    m_globalObject->syncTrayOptions(m_systrayIconTypeCombobox->currentIndex(),
                                    m_systrayCustomIconFN,
                                    m_systrayHideCheckbox->isChecked());


    settings.endGroup();


    settings.sync();
    emit configurationChanged(); // Ask MainWindow to reload some stuff

    this->hide();   // this->close() would end the program if mainWindow was hidden

    qDebug() << "ConfigDialog: config saved";
}



void ConfigDialog::pickCustomIconFile()
{
    QString newTrayIconFN = QFileDialog::getOpenFileName(this,
                                                         tr("Select custom icon"),
                                                         m_systrayIconLastDir,
                                                         tr("Image files")
                                                         + " (*.png *.jpg *.jpe "
                                                           "*.jpeg *.gif);;"
                                                         + tr("All files")
                                                         + " (*)");

    if (!newTrayIconFN.isEmpty())
    {
        qDebug() << "Selected" << newTrayIconFN << "as new custom tray icon";
        QFileInfo fileInfo(newTrayIconFN);
        m_systrayIconLastDir = fileInfo.path();

        QPixmap iconPixmap = QPixmap(newTrayIconFN);
        if (!iconPixmap.isNull())
        {
            m_systrayCustomIconFN = newTrayIconFN;
            m_systrayCustomIconButton->setIcon(QIcon(m_systrayCustomIconFN));
            m_systrayCustomIconButton->setToolTip("<b></b>"
                                                  + m_systrayCustomIconFN);
        }
        else
        {
            QMessageBox::warning(this,
                                 tr("Invalid image"),
                                 tr("The selected image is not valid."));
            qDebug() << "Invalid tray icon file selected";
        }
    }
}


void ConfigDialog::showDemoNotification(int notificationStyle)
{
    m_notifStatusLabel->clear();

    if (notificationStyle == FDNotifications::NoNotifications)
    {
        return;
    }


    this->syncNotifierOptions();

    QString demoNotificationText = this->checkNotifications(notificationStyle);
    m_fdNotifier->showMessage(demoNotificationText);
}


void ConfigDialog::toggleNotificationDetails(int currentOption)
{
    bool state = true;
    if (currentOption == 2) // No notifications; disable details so it's clearer
    {
        state = false;
    }

    m_notifDurationSpinbox->setEnabled(state // This one also depends on another option
                                       && !m_notifPersistentCheckbox->isChecked());
    m_notifPersistentCheckbox->setEnabled(state);
    m_notifTaskbarCheckbox->setEnabled(state);

    m_notifyNewTLCheckbox->setEnabled(state);
    m_notifyHLTLCheckbox->setEnabled(state);
    m_notifyNewMWCheckbox->setEnabled(state);
    m_notifyHLMWCheckbox->setEnabled(state);
    m_notifyErrorsCheckbox->setEnabled(state);
}


void ConfigDialog::toggleCustomIconButton(int currentOption)
{
    // Enable only for last option, "Custom icon"
    m_systrayCustomIconButton->setEnabled(currentOption == 3);
}


//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// PROTECTED ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////


void ConfigDialog::closeEvent(QCloseEvent *event)
{
    this->hide();
    event->ignore();
}

void ConfigDialog::hideEvent(QHideEvent *event)
{
    QSettings settings;
    settings.setValue("ConfigDialog/configWindowSize", this->size());

    event->accept();
}
