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

#include "gui/settings/settingsbrowsermail.h"

#include "gui/dialogs/filedialog.h"
#include "gui/dialogs/formmain.h"
#include "gui/feedmessageviewer.h"
#include "gui/reusable/networkproxydetails.h"
#include "gui/webbrowser.h"
#include "gui/webviewers/webviewer.h"
#include "miscellaneous/application.h"
#include "miscellaneous/externaltool.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/settings.h"
#include "network-web/webfactory.h"

#include <QInputDialog>
#include <QNetworkProxy>

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

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

  m_ui->m_lblExternalBrowserInfo->setHelpText(tr("Note that \"%1\" (without quotation marks) "
                                                 "is placeholder for URL of selected message."),
                                              false);

  m_ui->m_lblExternalEmailInfo->setHelpText(tr("Placeholders:\n"
                                               " \u2022 %1 - title of selected message,\n"
                                               " \u2022 %2 - body of selected message."),
                                            false);

  m_ui->m_lblToolInfo
    ->setHelpText(tr("On this page, you can setup a list of external tools which can open URLs. If "
                     "you setup domain (without leading \"www.\") then the tool will be directly used "
                     "to open all clicked links from that domain. You can separate multiple domains with ','."),
                  false);

  m_ui->m_btnAddTool->setIcon(qApp->icons()->fromTheme(QSL("list-add")));
  m_ui->m_btnEditTool->setIcon(qApp->icons()->fromTheme(QSL("document-edit")));
  m_ui->m_btnDeleteTool->setIcon(qApp->icons()->fromTheme(QSL("list-remove")));
  m_ui->m_listTools->setHeaderLabels({tr("Name"), tr("Executable"), tr("Parameters"), tr("Domain")});
  m_ui->m_listTools->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
  m_ui->m_listTools->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch);

  connect(m_ui->m_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_grpCustomExternalEmail, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_txtExternalBrowserExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_txtExternalEmailExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);

  connect(m_ui->m_cmbExternalBrowserPreset,
          static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
          this,
          &SettingsBrowserMail::changeDefaultBrowserArguments);
  connect(m_ui->m_btnExternalBrowserExecutable,
          &QPushButton::clicked,
          this,
          &SettingsBrowserMail::selectBrowserExecutable);
  connect(m_ui->m_cmbExternalEmailPreset,
          static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
          this,
          &SettingsBrowserMail::changeDefaultEmailArguments);
  connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable);
  connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_btnEditTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings);
  connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::addExternalTool);
  connect(m_ui->m_btnEditTool, &QPushButton::clicked, this, &SettingsBrowserMail::editSelectedExternalTool);
  connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::deleteSelectedExternalTool);
  connect(m_ui->m_listTools,
          &QTreeWidget::currentItemChanged,
          this,
          [this](QTreeWidgetItem* current, QTreeWidgetItem* previous) {
            Q_UNUSED(previous)

            m_ui->m_btnDeleteTool->setEnabled(current != nullptr);
            m_ui->m_btnEditTool->setEnabled(current != nullptr);
          });
  connect(m_ui->m_listTools, &QTreeWidget::itemChanged, this, &SettingsBrowserMail::dirtifySettings);

  SettingsPanel::loadUi();
}

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

QIcon SettingsBrowserMail::icon() const {
  return qApp->icons()->fromTheme(QSL("tools"), QSL("application-x-executable"));
}

void SettingsBrowserMail::changeDefaultBrowserArguments(int index) {
  if (index != 0) {
    m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString());
  }
}

void SettingsBrowserMail::selectBrowserExecutable() {
  const QString executable_file = FileDialog::openFileName(this,
                                                           tr("Select web browser executable"),
                                                           qApp->homeFolder(),
                                                           {},
  //: File filter for external browser selection dialog.
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
                                                           tr("Executables (*)"));
#else
                                                           tr("Executables (*.*)"));
#endif

  if (!executable_file.isEmpty()) {
    m_ui->m_txtExternalBrowserExecutable->setText(QDir::toNativeSeparators(executable_file));
  }
}

QVector<ExternalTool> SettingsBrowserMail::externalTools() const {
  QVector<ExternalTool> list;

  for (int i = 0; i < m_ui->m_listTools->topLevelItemCount(); i++) {
    auto* it = m_ui->m_listTools->topLevelItem(i);
    list.append(ExternalTool(it->text(0),
                             it->text(1),
                             it->text(2),
                             it->text(3).split(QL1C(','), SPLIT_BEHAVIOR::SkipEmptyParts)));
  }

  return list;
}

void SettingsBrowserMail::setExternalTools(const QList<ExternalTool>& list) {
  for (const ExternalTool& tool : list) {
    QTreeWidgetItem* item =
      new QTreeWidgetItem(m_ui->m_listTools,
                          {tool.name(), tool.executable(), tool.parameters(), tool.domains().join(QL1C(','))});

    item->setFlags(item->flags() | Qt::ItemFlag::ItemIsEditable);

    m_ui->m_listTools->addTopLevelItem(item);
  }
}

void SettingsBrowserMail::changeDefaultEmailArguments(int index) {
  if (index != 0) {
    m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString());
  }
}

void SettingsBrowserMail::selectEmailExecutable() {
  QString executable_file = FileDialog::openFileName(this,
                                                     tr("Select e-mail executable"),
                                                     qApp->homeFolder(),
                                                     {},
  //: File filter for external e-mail selection dialog.
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
                                                     tr("Executables (*)"));
#else
                                                     tr("Executables (*.*)"));
#endif

  if (!executable_file.isEmpty()) {
    m_ui->m_txtExternalEmailExecutable->setText(QDir::toNativeSeparators(executable_file));
  }
}

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

  // Load settings of web browser GUI.
  m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1"));
  m_ui->m_txtExternalBrowserExecutable
    ->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserExecutable)).toString());
  m_ui->m_txtExternalBrowserArguments
    ->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserArguments)).toString());
  m_ui->m_grpCustomExternalBrowser
    ->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool());

  // Load settings of e-mail.
  m_ui->m_cmbExternalEmailPreset->addItem(QSL("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\""));
  m_ui->m_txtExternalEmailExecutable
    ->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString());
  m_ui->m_txtExternalEmailArguments
    ->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString());
  m_ui->m_grpCustomExternalEmail
    ->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool());

  setExternalTools(ExternalTool::toolsFromSettings());
  onEndLoadSettings();
}

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

  // Save settings of GUI of web browser.
  settings()->setValue(GROUP(Browser),
                       Browser::CustomExternalBrowserEnabled,
                       m_ui->m_grpCustomExternalBrowser->isChecked());
  settings()->setValue(GROUP(Browser),
                       Browser::CustomExternalBrowserExecutable,
                       m_ui->m_txtExternalBrowserExecutable->text());
  settings()->setValue(GROUP(Browser),
                       Browser::CustomExternalBrowserArguments,
                       m_ui->m_txtExternalBrowserArguments->text());

  // Save settings of e-mail.
  settings()->setValue(GROUP(Browser),
                       Browser::CustomExternalEmailExecutable,
                       m_ui->m_txtExternalEmailExecutable->text());
  settings()->setValue(GROUP(Browser),
                       Browser::CustomExternalEmailArguments,
                       m_ui->m_txtExternalEmailArguments->text());
  settings()->setValue(GROUP(Browser),
                       Browser::CustomExternalEmailEnabled,
                       m_ui->m_grpCustomExternalEmail->isChecked());

  auto tools = externalTools();
  ExternalTool::setToolsToSettings(tools);

  onEndSaveSettings();
}

void SettingsBrowserMail::addExternalTool() {
#if defined(IS_FLATPAK_BUILD)
  QString exec;
#else
  QString exec = askForExecutable(QString());

  if (exec.isEmpty()) {
    return;
  }
#endif
  QTreeWidgetItem* item =
    new QTreeWidgetItem(m_ui->m_listTools, {QFileInfo(exec).baseName(), QDir::toNativeSeparators(exec), QSL("")});

  item->setFlags(item->flags() | Qt::ItemFlag::ItemIsEditable);
  m_ui->m_listTools->addTopLevelItem(item);
}

QString SettingsBrowserMail::askForExecutable(const QString& old_exec) const {
  QString executable_file = FileDialog::openFileName(window(),
                                                     tr("Select external tool"),
                                                     QFileInfo(old_exec).absolutePath(),
                                                     QFileInfo(old_exec).fileName(),
#if defined(Q_OS_WIN)
                                                     tr("Executables (*.*)"),
#else
                                                     tr("Executables (*)"),
#endif
                                                     nullptr,
                                                     GENERAL_REMEMBERED_PATH);

  return QDir::toNativeSeparators(executable_file);
}

void SettingsBrowserMail::editSelectedExternalTool() {
  auto* cur_it = m_ui->m_listTools->currentItem();

  if (cur_it == nullptr) {
    return;
  }

  QString new_exec = askForExecutable(m_ui->m_listTools->currentItem()->text(1));

  if (new_exec.isEmpty()) {
    return;
  }

  m_ui->m_listTools->currentItem()->setText(1, new_exec);
}

void SettingsBrowserMail::deleteSelectedExternalTool() {
  if (!m_ui->m_listTools->selectedItems().isEmpty()) {
    m_ui->m_listTools
      ->takeTopLevelItem(m_ui->m_listTools->indexOfTopLevelItem(m_ui->m_listTools->selectedItems().first()));
  }
}
