#include <Widget/Button/Button.hpp>
#include <ToolTip/ToolTip.hpp>
#include <Color/Color.hpp>
#include <Sound/Sound.hpp>

Button::Button(std::string text, Button::Callback callback) :
    text(text),
    callback(callback),
    down(false),
    getFaceColor([]() {return Color::action;}),
    getIsEnabled([]() {return true;}),
    icon(nullptr)
{}

Button* Button::withToolTip(std::string tip)
{
    toolTip = tip;
    return this;
}

Button* Button::withFaceColor(glm::vec4 color)
{
    getFaceColor = [color](){return color;};
    return this;
}

Button* Button::withFaceColor(FaceColorCallback callback)
{
    getFaceColor = callback;
    return this;
}

Button* Button::enabledIf(IsEnabledCallback callback)
{
    getIsEnabled = callback;
    return this;
}

Button* Button::withIcon(Material &icon)
{
    this->icon = &icon;
    return this;
}

void Button::draw(GraphicsContext &context)
{
    bool enabled = getIsEnabled();
    int faceDropHeight = (enabled && isMouseInside() && down) ? clickDropHeight : 0;

    context.color = Color::shadow;
    context.drawRect(0, faceDropHeight, m_size.x, m_size.y - faceDropHeight);

    context.color = hoverLerp.sample((enabled && isMouseInside()) ? Color::focused : glm::vec4(0.0f));
    context.drawRect(0, faceDropHeight, m_size.x, m_size.y - shadowDropHeight + 1);

    context.color = enabled ? getFaceColor() : Color::disabled;
    context.drawRect(1, faceDropHeight + 1, m_size.x - 2, m_size.y - shadowDropHeight - 1);

    glm::ivec2 textSize = GraphicsContext::measureText(Font::generic, text);
    if (text.size() == 0)
    {
        textSize.x = 0;
    }

    if (icon != nullptr)
    {
        textSize.x += iconSize + 2 * iconMargin;
    }

    glm::ivec2 startPos = (m_size - textSize) / 2;
    if (icon != nullptr)
    {
        context.color = glm::vec4(1.0f);
        context.drawMaterial(*icon, startPos.x + 1, startPos.y - 1 + faceDropHeight);
        startPos.x += iconSize + 2 * iconMargin;
    }

    if (enabled)
    {
        context.color = Color::shadow;
        context.drawText(Font::generic, startPos.x, startPos.y + faceDropHeight, text);
    }

    context.color = enabled ? glm::vec4(1.0f) : Color::faded;

    context.drawText(Font::generic, startPos.x, startPos.y - 1 + faceDropHeight, text);
    if (isMouseInside() && toolTip.has_value())
    {
        ToolTip &tip = context.createToolTip();
        tip.addLine(glm::vec4(1.0f), *toolTip);
    }
}

glm::ivec2 Button::getMinSize()
{
    int width = GraphicsContext::measureText(Font::generic, text).x;
    if (text.size() == 0)
    {
        width = 0;
    }

    if (icon != nullptr)
    {
        width += iconSize + 2 * iconMargin;
    }

    return glm::ivec2(width + buttonMargin * 2, totalHeight);
}

void Button::onMouseUp(Uint8 button)
{
    Widget::onMouseUp(button);

    if (button == SDL_BUTTON_LEFT)
    {
        down = false;

        if (getIsEnabled() && isMouseInside())
        {
            Sound::buttonClick.play();
            callback();
        }
    }
}

void Button::onMouseDown(Uint8 button)
{
    Widget::onMouseDown(button);
    
    if (button == SDL_BUTTON_LEFT && isMouseInside())
    {
        down = true;
    }
}