#include <ToolTip/ToolTip.hpp>
#include <Utilities/Utilities.hpp>
#include <Widget/AnimationView/AnimationView.hpp>
#include <Widget/Builder/Builder.hpp>
#include <Widget/IconLabel/IconLabel.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/Layout/CompoundWidget/CompoundWidget.hpp>
#include <Widget/Layout/CompoundWidget/PingView/PingView.hpp>

PingView::PingView(Pinger &pinger) :
    CompoundWidget(
        new Builder<Pinger::State>(
            [&pinger]() { return pinger.getState(); },
            [&pinger](Pinger::State state) -> Widget*
            {            
                if (state == Pinger::State::Pinging)
                {
                    return new AnimationView(Animation::pinging);
                }
                else if (state == Pinger::State::Success)
                {
                    Uint32 ms = pinger.getTimeMS();
                    if (ms < 30)
                    {
                        return new IconLabel(Material::ping4);
                    }
                    else if (ms < 60)
                    {
                        return new IconLabel(Material::ping3);
                    }
                    else if (ms < 100)
                    {
                        return new IconLabel(Material::ping2);
                    }
                    else
                    {
                        return new IconLabel(Material::ping1);
                    }
                }
                else if (state == Pinger::State::Error)
                {
                    return new IconLabel(Material::pingError);
                }
                else
                {
                    crash("Unexpected pinger state.");
                }
            }
        )
    ),
    pinger(pinger)
{}

void PingView::draw(GraphicsContext &context)
{
    CompoundWidget::draw(context);

    if (!isMouseInside())
    {
        return;
    }

    ToolTip &tip = context.createToolTip();
    tip.addLine(glm::vec4(1.0f), pinger.getAddr());

    Pinger::State state = pinger.getState();
    switch (state)
    {
    case Pinger::State::Pinging:
        tip.addLine(Color::faded, "Pinging...");
        break;
    case Pinger::State::Error:
        tip.addLine(Color::error, pinger.getError());
        break;
    case Pinger::State::Success:
        tip.addLine(Color::faded, formatString("Ping: $+ms", pinger.getTimeMS()));
        break;
    }

    if (state != Pinger::State::Pinging && envVars.devMode)
    {
        tip.addLine(Color::faded, pinger.getResolvedAddr());
    }
}