#pragma once
#include <QCoreApplication>
#include "builtin_icon.hpp"
#include "clipboard-actions.hpp"
#include "qml/edit-keywords-view-host.hpp"
#include "services/clipboard/clipboard-service.hpp"
#include "services/toast/toast-service.hpp"
#include "ui/alert/alert.hpp"

class PasteClipboardSelection : public PasteToFocusedWindowAction {
  QString m_id;
  void execute(ApplicationContext *ctx) override {
    setConcealed();
    loadClipboardData(Clipboard::SelectionRecordHandle(m_id));
    PasteToFocusedWindowAction::execute(ctx);
  }

public:
  PasteClipboardSelection(const QString &id) : PasteToFocusedWindowAction(), m_id(id) {}
};

class CopyClipboardSelection : public AbstractAction {
  Q_DECLARE_TR_FUNCTIONS(CopyClipboardSelection)
  QString m_id;
  void execute(ApplicationContext *ctx) override {
    auto clipman = ctx->services->clipman();
    auto toast = ctx->services->toastService();
    if (clipman->copySelectionRecord(m_id, {.concealed = true})) {
      ctx->navigation->showHud(tr("Selection copied to clipboard"));
      return;
    }
    toast->failure(tr("Failed to copy to clipboard"));
  }

public:
  CopyClipboardSelection(const QString &id)
      : AbstractAction(tr("Copy to clipboard"), BuiltinIcon::CopyClipboard), m_id(id) {}
};

class RemoveSelectionAction : public AbstractAction {
  Q_DECLARE_TR_FUNCTIONS(RemoveSelectionAction)
  QString m_id;
  void execute(ApplicationContext *ctx) override {
    auto clipman = ctx->services->clipman();
    auto toast = ctx->services->toastService();
    if (clipman->removeSelection(m_id)) {
      toast->setToast(tr("Entry removed"));
    } else {
      toast->setToast(tr("Failed to remove entry"), ToastStyle::Danger);
    }
  }

public:
  RemoveSelectionAction(const QString &id)
      : AbstractAction(tr("Remove entry"), ImageURL::builtin(BuiltinIcon::Trash)), m_id(id) {
    setStyle(AbstractAction::Style::Danger);
  }
};

class PinClipboardAction : public AbstractAction {
  Q_DECLARE_TR_FUNCTIONS(PinClipboardAction)
  QString m_id;
  bool m_value;
  void execute(ApplicationContext *ctx) override {
    if (ctx->services->clipman()->setPinned(m_id, m_value)) {
      ctx->services->toastService()->success(m_value ? tr("Selection pinned") : tr("Selection unpinned"));
    } else {
      ctx->services->toastService()->failure(tr("Failed to change pin status"));
    }
  }

public:
  PinClipboardAction(const QString &id, bool value)
      : AbstractAction(value ? tr("Pin") : tr("Unpin"), ImageURL::builtin(BuiltinIcon::Pin)), m_id(id),
        m_value(value) {}
};

class EditClipboardKeywordsAction : public AbstractAction {
  Q_DECLARE_TR_FUNCTIONS(EditClipboardKeywordsAction)
  QString m_id;
  void execute(ApplicationContext *ctx) override {
    auto clipman = ctx->services->clipman();
    auto id = m_id;
    auto view =
        new EditKeywordsViewHost([clipman, id]() { return clipman->retrieveKeywords(id).value_or(""); },
                                 [clipman, id](const QString &kw) { return clipman->setKeywords(id, kw); },
                                 tr("Additional keywords that will be used to index this selection."));
    ctx->navigation->pushView(view);
    ctx->navigation->setNavigationTitle(title());
  }

public:
  QString title() const override { return tr("Edit keywords"); }
  std::optional<ImageURL> icon() const override { return ImageURL::builtin(BuiltinIcon::Text); }
  EditClipboardKeywordsAction(const QString &id) : m_id(id) {}
};

class RemoveAllSelectionsAction : public AbstractAction {
  Q_DECLARE_TR_FUNCTIONS(RemoveAllSelectionsAction)
  void execute(ApplicationContext *ctx) override {
    auto alert = new CallbackAlertWidget();
    alert->setTitle(tr("Are you sure?"));
    alert->setMessage(tr("All your clipboard history will be lost forever"));
    alert->setConfirmText(tr("Delete all"), SemanticColor::Red);
    alert->setConfirmCallback([ctx]() {
      auto toast = ctx->services->toastService();
      auto clipman = ctx->services->clipman();
      if (clipman->removeAllSelections()) {
        toast->success(tr("All selections were removed"));
      } else {
        toast->failure(tr("Failed to remove all selections"));
      }
    });
    ctx->navigation->setDialog(alert);
  }

public:
  QString title() const override { return tr("Remove all"); }
  std::optional<ImageURL> icon() const override { return ImageURL::builtin(BuiltinIcon::Trash); }
  RemoveAllSelectionsAction() { setStyle(AbstractAction::Style::Danger); }
};
