#ifndef BUTTON_HPP_
#define BUTTON_HPP_

#include <Utilities/StandardLerping.hpp>
#include <string>
#include <functional>
#include <optional>

#include <Widget/Widget.hpp>

/**
 * @brief Represents the button widget.
 */
class Button : public Widget
{
public:
    typedef std::function<void()> Callback;
    typedef std::function<bool()> IsEnabledCallback;
    typedef std::function<glm::vec4()> FaceColorCallback;

private:
    static constexpr int buttonMargin = 3;
    static constexpr int totalHeight = 15;
    static constexpr int shadowDropHeight = 3;
    static constexpr int clickDropHeight = 2;
    static constexpr int iconSize = 8;
    static constexpr int iconMargin = 1;
    
    std::string text;
    Callback callback;
    bool down;
    std::optional<std::string> toolTip;
    FaceColorCallback getFaceColor;
    IsEnabledCallback getIsEnabled;
    Material* icon;
    StandardLerping<glm::vec4> hoverLerp;

public:
    /**
     * @brief Construct a button.
     * 
     * @param text The text to display in the button.
     * @param callback The callback to call when the button is clicked.
     */
    Button(std::string text, Callback callback);

    /**
     * @brief Return this button with a different tooltip.
     * 
     * @param tip The tooltip.
     */
    Button* withToolTip(std::string tip);

    /**
     * @brief Return this button with a different face color.
     * 
     * By default, `Color::action` is used.
     */
    Button* withFaceColor(glm::vec4 color);

    /**
     * @brief Return this button with the specified callback for face color.
     */
    Button* withFaceColor(FaceColorCallback callback);

    /**
     * @brief Return this button, enabled only when the callback returns true.
     * 
     * The default callback always returns true, so a button is always enabled by default.
     */
    Button* enabledIf(IsEnabledCallback callback);

    /**
     * @brief Return this button with a different icon.
     * 
     * By default there is no icon.
     */
    Button* withIcon(Material &icon);

    virtual void draw(GraphicsContext &context) override;
    virtual glm::ivec2 getMinSize() override;
    virtual void onMouseDown(Uint8 button) override;
    virtual void onMouseUp(Uint8 button) override;
};

#endif