#ifdef CHATTERINO_HAVE_PLUGINS
#    include "widgets/settingspages/PluginsPage.hpp"

#    include "Application.hpp"
#    include "controllers/plugins/PluginController.hpp"
#    include "singletons/Paths.hpp"
#    include "singletons/Settings.hpp"
#    include "util/Helpers.hpp"
#    include "util/LayoutCreator.hpp"
#    include "util/RemoveScrollAreaBackground.hpp"

#    include <QCheckBox>
#    include <QFormLayout>
#    include <QGroupBox>
#    include <QLabel>
#    include <QObject>
#    include <QPushButton>
#    include <QWidget>

namespace chatterino {

PluginsPage::PluginsPage()
    : scrollAreaWidget_(nullptr)
    , dataFrame_(nullptr)
{
    LayoutCreator<PluginsPage> layoutCreator(this);
    auto scrollArea = layoutCreator.emplace<QScrollArea>();

    auto widget = scrollArea.emplaceScrollAreaWidget();
    this->scrollAreaWidget_ = widget;
    removeScrollAreaBackground(scrollArea.getElement(), widget.getElement());

    auto layout = widget.setLayoutType<QVBoxLayout>();

    {
        auto group = layout.emplace<QGroupBox>("General plugin settings");
        this->generalGroup = group.getElement();
        auto groupLayout = group.setLayoutType<QFormLayout>();
        auto *description = new QLabel(
            "You can load plugins by putting them into " +
            formatRichNamedLink("file:///" + getPaths()->pluginsDirectory,
                                "the Plugins directory") +
            ". Each one is a new directory.");
        description->setOpenExternalLinks(true);
        description->setWordWrap(true);
        description->setStyleSheet("color: #bbb");
        groupLayout->addRow(description);

        auto *box = this->createCheckBox("Enable plugins",
                                         getSettings()->pluginsEnabled);
        QObject::connect(box, &QCheckBox::released, [this]() {
            this->rebuildContent();
        });
        groupLayout->addRow(box);
    }

    this->rebuildContent();
}

void PluginsPage::rebuildContent()
{
    if (this->dataFrame_ != nullptr)
    {
        this->dataFrame_->deleteLater();
        this->dataFrame_ = nullptr;
    }
    auto frame = LayoutCreator<QFrame>(new QFrame(this));
    this->dataFrame_ = frame.getElement();
    this->scrollAreaWidget_.append(this->dataFrame_);
    auto layout = frame.setLayoutType<QVBoxLayout>();
    layout->setParent(this->dataFrame_);
    for (const auto &[id, plugin] : getApp()->plugins->plugins())
    {
        auto groupHeaderText =
            QString("%1 (%2, from %3)")
                .arg(plugin->meta.name,
                     QString::fromStdString(plugin->meta.version.to_string()),
                     id);
        auto groupBox = layout.emplace<QGroupBox>(groupHeaderText);
        groupBox->setParent(this->dataFrame_);
        auto pluginEntry = groupBox.setLayoutType<QFormLayout>();
        pluginEntry->setParent(groupBox.getElement());

        if (!plugin->meta.isValid())
        {
            QString errors = "<ul>";
            for (const auto &err : plugin->meta.errors)
            {
                errors += "<li>" + err.toHtmlEscaped() + "</li>";
            }
            errors += "</ul>";

            auto *warningLabel = new QLabel(
                "There were errors while loading metadata for this plugin:" +
                    errors,
                this->dataFrame_);
            warningLabel->setTextFormat(Qt::RichText);
            warningLabel->setStyleSheet("color: #f00");
            pluginEntry->addRow(warningLabel);
        }

        auto *description =
            new QLabel(plugin->meta.description, this->dataFrame_);
        description->setWordWrap(true);
        description->setStyleSheet("color: #bbb");
        pluginEntry->addRow(description);

        QString authorsTxt;
        for (const auto &author : plugin->meta.authors)
        {
            if (!authorsTxt.isEmpty())
            {
                authorsTxt += ", ";
            }

            authorsTxt += author;
        }
        pluginEntry->addRow("Authors",
                            new QLabel(authorsTxt, this->dataFrame_));

        if (!plugin->meta.homepage.isEmpty())
        {
            auto *homepage = new QLabel(formatRichLink(plugin->meta.homepage),
                                        this->dataFrame_);
            homepage->setOpenExternalLinks(true);
            pluginEntry->addRow("Homepage", homepage);
        }
        pluginEntry->addRow("License",
                            new QLabel(plugin->meta.license, this->dataFrame_));

        QString commandsTxt;
        for (const auto &cmdName : plugin->listRegisteredCommands())
        {
            if (!commandsTxt.isEmpty())
            {
                commandsTxt += ", ";
            }

            commandsTxt += cmdName;
        }
        pluginEntry->addRow("Commands",
                            new QLabel(commandsTxt, this->dataFrame_));

        if (plugin->meta.isValid())
        {
            QString toggleTxt = "Enable";
            if (PluginController::isPluginEnabled(id))
            {
                toggleTxt = "Disable";
            }

            auto *toggleButton = new QPushButton(toggleTxt, this->dataFrame_);
            QObject::connect(
                toggleButton, &QPushButton::pressed, [name = id, this]() {
                    std::vector<QString> val =
                        getSettings()->enabledPlugins.getValue();
                    if (PluginController::isPluginEnabled(name))
                    {
                        val.erase(std::remove(val.begin(), val.end(), name),
                                  val.end());
                    }
                    else
                    {
                        val.push_back(name);
                    }
                    getSettings()->enabledPlugins.setValue(val);
                    getApp()->plugins->reload(name);
                    this->rebuildContent();
                });
            pluginEntry->addRow(toggleButton);
        }

        auto *reloadButton = new QPushButton("Reload", this->dataFrame_);
        QObject::connect(reloadButton, &QPushButton::pressed,
                         [name = id, this]() {
                             getApp()->plugins->reload(name);
                             this->rebuildContent();
                         });
        pluginEntry->addRow(reloadButton);
    }
}

}  // namespace chatterino

#endif
