// For license of this file, see <project-root-folder>/LICENSE.md.

#include "gui/settings/settingsnotifications.h"

#include "definitions/globals.h"
#include "gui/notifications/notificationseditor.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/notificationfactory.h"
#include "miscellaneous/settings.h"

#include <QDir>
#include <QScreen>

SettingsNotifications::SettingsNotifications(Settings* settings, QWidget* parent)
  : SettingsPanel(settings, parent), m_ui(nullptr) {}

SettingsNotifications::~SettingsNotifications() {
  if (m_ui != nullptr) {
    delete m_ui;
  }
}

void SettingsNotifications::loadUi() {
  m_ui = new Ui::SettingsNotifications();
  m_ui->setupUi(this);

  m_ui->m_lblInfo
    ->setHelpText(tr("There are some built-in notification sounds. Just start typing \":\" and they will show up."),
                  true);

  m_ui->m_lblNativeNotif->setHelpText(tr("Note that native notifications might have some OS-dependent limitations. For "
                                         "example Windows OS is known to limit the amount of notification originating "
                                         "from each app during short span of time."),
                                      true);

  connect(m_ui->m_checkEnableNotifications, &QCheckBox::toggled, this, &SettingsNotifications::dirtifySettings);
  connect(m_ui->m_editor, &NotificationsEditor::someNotificationChanged, this, &SettingsNotifications::dirtifySettings);

  connect(m_ui->m_rbCustomNotifications, &QRadioButton::toggled, this, &SettingsNotifications::dirtifySettings);
  connect(m_ui->m_rbCustomNotifications, &QRadioButton::toggled, this, &SettingsNotifications::requireRestart);

  connect(m_ui->m_rbNativeNotifications, &QRadioButton::toggled, this, &SettingsNotifications::dirtifySettings);
  connect(m_ui->m_rbNativeNotifications, &QRadioButton::toggled, this, &SettingsNotifications::requireRestart);

  connect(m_ui->m_sbDuration,
          QOverload<int>::of(&QSpinBox::valueChanged),
          this,
          &SettingsNotifications::dirtifySettings);
  connect(m_ui->m_sbScreen, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsNotifications::dirtifySettings);
  connect(m_ui->m_sbMargin, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsNotifications::dirtifySettings);
  connect(m_ui->m_sbWidth, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsNotifications::dirtifySettings);
  connect(m_ui->m_sbOpacity,
          QOverload<int>::of(&QSpinBox::valueChanged),
          this,
          &SettingsNotifications::dirtifySettings);

  connect(m_ui->m_sbScreen, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsNotifications::showScreenInfo);

  connect(m_ui->m_cbCustomNotificationsPosition,
          QOverload<int>::of(&QComboBox::currentIndexChanged),
          this,
          &SettingsNotifications::dirtifySettings);

  SettingsPanel::loadUi();
}

QIcon SettingsNotifications::icon() const {
  return qApp->icons()->fromTheme(QSL("notifications"), QSL("dialog-information"));
}

void SettingsNotifications::loadSettings() {
  onBeginLoadSettings();

  m_ui->m_sbScreen->setMinimum(-1);
  m_ui->m_sbScreen->setMaximum(QGuiApplication::screens().size() - 1);

  auto poss = enumToStrings<ToastNotificationsManager::NotificationPosition>();

  for (const auto& pos : poss) {
    m_ui->m_cbCustomNotificationsPosition->addItem(ToastNotificationsManager::textForPosition(pos.first), pos.first);
  }

  // Load fancy notification settings.
  m_ui->m_checkEnableNotifications
    ->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::EnableNotifications)).toBool());
  m_ui->m_editor->loadNotifications(qApp->notifications()->allNotifications());

  if (qApp->isWayland()) {
    // Wayland does not support fancy notifications, only system ones.
    m_ui->m_rbNativeNotifications->setChecked(true);
    m_ui->m_rbCustomNotifications->setEnabled(false);
    m_ui->m_rbCustomNotifications
      ->setText(tr("%1 (not supported on Wayland)").arg(m_ui->m_rbCustomNotifications->text()));
  }
  else {
    m_ui->m_rbNativeNotifications
      ->setChecked(!settings()->value(GROUP(GUI), SETTING(GUI::UseToastNotifications)).toBool());
  }

  m_ui->m_sbDuration->setValue(settings()->value(GROUP(GUI), SETTING(GUI::ToastNotificationsDuration)).toInt());
  m_ui->m_sbScreen->setValue(settings()->value(GROUP(GUI), SETTING(GUI::ToastNotificationsScreen)).toInt());
  m_ui->m_sbWidth->setValue(settings()->value(GROUP(GUI), SETTING(GUI::ToastNotificationsWidth)).toInt());
  m_ui->m_sbMargin->setValue(settings()->value(GROUP(GUI), SETTING(GUI::ToastNotificationsMargin)).toInt());
  m_ui->m_sbOpacity->setValue(settings()->value(GROUP(GUI), SETTING(GUI::ToastNotificationsOpacity)).toDouble() * 100);

  m_ui->m_cbCustomNotificationsPosition
    ->setCurrentIndex(m_ui->m_cbCustomNotificationsPosition
                        ->findData(settings()
                                     ->value(GROUP(GUI), SETTING(GUI::ToastNotificationsPosition))
                                     .value<ToastNotificationsManager::NotificationPosition>()));

  onEndLoadSettings();
}

void SettingsNotifications::saveSettings() {
  onBeginSaveSettings();

  // Save notifications.
  settings()->setValue(GROUP(GUI), GUI::EnableNotifications, m_ui->m_checkEnableNotifications->isChecked());
  qApp->notifications()->save(m_ui->m_editor->allNotifications(), settings());

  settings()->setValue(GROUP(GUI), GUI::UseToastNotifications, m_ui->m_rbCustomNotifications->isChecked());
  settings()->setValue(GROUP(GUI), GUI::ToastNotificationsDuration, m_ui->m_sbDuration->value());
  settings()->setValue(GROUP(GUI), GUI::ToastNotificationsScreen, m_ui->m_sbScreen->value());
  settings()->setValue(GROUP(GUI), GUI::ToastNotificationsWidth, m_ui->m_sbWidth->value());
  settings()->setValue(GROUP(GUI), GUI::ToastNotificationsMargin, m_ui->m_sbMargin->value());
  settings()->setValue(GROUP(GUI), GUI::ToastNotificationsOpacity, m_ui->m_sbOpacity->value() / 100.0);

  settings()->setValue(GROUP(GUI),
                       GUI::ToastNotificationsPosition,
                       m_ui->m_cbCustomNotificationsPosition->currentData()
                         .value<ToastNotificationsManager::NotificationPosition>());

  auto* toasts = qApp->toastNotifications();

  if (toasts != nullptr && m_ui->m_rbCustomNotifications->isChecked() &&
      m_ui->m_checkEnableNotifications->isChecked()) {
    toasts->resetNotifications(true);
    toasts->showNotification(Notification::Event::GeneralEvent,
                             GuiMessage(tr("How do I look?"),
                                        tr("Just testing new notifications settings. "
                                           "That's all."),
                                        QSystemTrayIcon::MessageIcon::Warning));
  }

  onEndSaveSettings();
}

void SettingsNotifications::showScreenInfo(int index) {
  QScreen* scr;

  if (index < 0 || index >= QGuiApplication::screens().size()) {
    scr = QGuiApplication::primaryScreen();
  }
  else {
    scr = QGuiApplication::screens().at(index);
  }

  m_ui->m_lblScreenInfo->setText(QSL("%1 (%2x%3)")
                                   .arg(scr->name(),
                                        QString::number(scr->virtualSize().width()),
                                        QString::number(scr->virtualSize().height())));
}
