#ifndef SETTINGS_PANEL_HPP_
#define SETTINGS_PANEL_HPP_

#include <Widget/Layout/CompoundWidget/CategoryView/CategoryView.hpp>
#include <Widget/Layout/CompoundWidget/CompoundWidget.hpp>
#include <Widget/Button/Button.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/Layout/Column/Column.hpp>
#include <Widget/Layout/CompoundWidget/CompoundWidget.hpp>
#include <Widget/Layout/Margin/Margin.hpp>
#include <Widget/Layout/ScrollPanel/ScrollPanel.hpp>
#include <Widget/Layout/Row/Row.hpp>
#include <Widget/Panel/Panel.hpp>
#include <Widget/ScancodePicker/ScancodePicker.hpp>
#include <Widget/Slider/Slider.hpp>
#include <Settings/Settings.hpp>
#include <Widget/Switch/Switch.hpp>
#include <Widget/Layout/Center/Center.hpp>
#include <Widget/Layout/CompoundWidget/ListView/ListView.hpp>
#include <Widget/TabList/TabList.hpp>
#include <Widget/Layout/CompoundWidget/TemperatureScaleSelector/TemperatureScaleSelector.hpp>
#include <Widget/ScancodePicker/ScancodePicker.hpp>
#include <string>

/**
 * @brief The widget displaying game settings.
 */
class SettingsPanel : public CompoundWidget
{
private:
    static constexpr int panelHeight = 100;

    Widget* makeKeyBindingSetting(const std::string &action, const char *displayName)
    {
        return new Row(
            new Center(new Label(formatString("$+:", displayName))),
            Layout::WithProportion<1>(),
            new Panel(),
            new Center(new ScancodePicker(action)),
            new Panel(glm::ivec2(2, 0)),
            (new Button(
                "",
                [action]()
                {
                    settings.keyBindings.resetActionMapping(action);
                    settings.save();
                }
            ))
                ->withIcon(Material::reset)
                ->withFaceColor(Color::reset)
                ->withToolTip("Reset to default")
        );
    }

public:
    template<typename... TArgs>
    SettingsPanel(TArgs... extraPages) : CompoundWidget(
        new CategoryView(
            "/settings-panel/category-view",
            extraPages...,

            #define DECL_COMMON_SETTING(type, name, defaultValue, shortDesc, longDesc, outputStmt, parse, buildWidget, ...)\
                new Row(\
                    new Center(new Label(shortDesc ":")),\
                    Layout::WithProportion<1>(),\
                    new Panel(glm::ivec2(4, 0)),\
                    buildWidget\
                ),
            #define DECL_SERVER_ONLY_SETTING(...)
            #define HIDDEN_SETTINGS(...)
            #define SETTINGS_SECTION(icon, label, body)\
                new Page(\
                    icon,\
                    label,\
                    new ScrollPanel(\
                        panelHeight,\
                        new ListView(\
                            body\
                            nullptr\
                        )\
                    )\
                ),
            #include <Settings/SettingsList.hpp>

            new Page(
                Material::keyBindings,
                "Key bindings",
                new ScrollPanel(
                    panelHeight,
                    new ListView(
                        #define DECL_INPUT_ACTION(name, displayName, ...) makeKeyBindingSetting(#name, displayName),
                        #define DECL_DEV_MODE_INPUT_ACTION(...) !envVars.devMode ? nullptr : DECL_INPUT_ACTION(__VA_ARGS__)
                        #include <InputAction/InputActionList.hpp>
                        nullptr
                    )
                )
            )
        )
    )
    {}
};

#endif