#ifndef SPIN_BOX_HPP_
#define SPIN_BOX_HPP_

#include <GraphicsContext/GraphicsContext.hpp>
#include <Widget/Builder/Builder.hpp>
#include <Widget/Button/Button.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/Layout/Center/Center.hpp>
#include <Widget/Layout/Column/Column.hpp>
#include <Widget/Layout/CompoundWidget/CompoundWidget.hpp>
#include <Widget/Layout/Frame/Frame.hpp>
#include <Widget/Layout/Row/Row.hpp>
#include <Widget/Panel/Panel.hpp>
#include <Widget/Widget.hpp>
#include <functional>

/**
 * @brief A widget which allows a value to be decremented and incremented.
 */
template<typename TValue>
class SpinBox final : public CompoundWidget
{
public:
    typedef std::function<void()> ChangedCallback;

private:
    TValue &currentValue;
    TValue minValue;
    TValue maxValue;
    ChangedCallback onChanged;

public:
    SpinBox(
        TValue &currentValue,
        TValue minValue,
        TValue maxValue,
        ChangedCallback onChanged = [](){}
    ) : currentValue(currentValue),
        minValue(minValue),
        maxValue(maxValue),
        onChanged(onChanged)
    {
        addChildren(
            new Row(
                (new Button(
                    "-",
                    [this, minValue, onChanged]()
                    {
                        if (this->currentValue != minValue)
                        {
                            this->currentValue--;
                            onChanged();
                        }
                    }
                ))->withFaceColor(Color::negativeStat),
                new Frame(
                    glm::vec4(0.0f, 0.0f, 0.0f, 1.0f),
                    new Builder<TValue>(
                        this->currentValue,
                        [](TValue value)
                        {
                            return new Column(
                                new Panel(glm::ivec2(30, 0)),
                                new Center(new Label(formatString("$+", value)))
                            );
                        }
                    )
                ),
                (new Button(
                    "+",
                    [this, maxValue, onChanged]()
                    {
                        if (this->currentValue != maxValue)
                        {
                            this->currentValue++;
                            onChanged();
                        }
                    }
                ))->withFaceColor(Color::positiveStat)
            )
        );
    }
};

#endif