#include "pch.h"
#include "log.h"
#include "legacy_ui_overlay_services.h"
#include "node_slider.h"
#include "shader.h"

Node* NodeSliderH::clone_instantiate() const
{
    return new NodeSliderH();
}

void NodeSliderH::clone_copy(Node* dest) const
{
    NodeBorder::clone_copy(dest);
    NodeSliderH* n = static_cast<NodeSliderH*>(dest);
    n->m_value = m_value;
}

void NodeSliderH::init()
{
    SetPadding(1, 1, 1, 1);
    SetWidthP(100);
    SetHeightP(100);
    m_color = glm::vec4(1);
}

void NodeSliderH::draw()
{
    NodeBorder::draw();

    auto sz = GetSize();
    glm::vec2 cur_size = sz;
    cur_size[m_comp] = 10;
    glm::mat4 scale = glm::scale(glm::vec3(cur_size, 1.f));
    glm::vec2 cur_pos = m_pos;
    cur_pos[m_comp] += (m_comp == 0 ? m_value : 1.f - m_value) * sz[m_comp];
    cur_pos[1 - m_comp] += sz[1 - m_comp] * 0.5f;
    glm::mat4 pos = glm::translate(glm::vec3(cur_pos , 0));
    auto mvp = m_proj * pos * scale;

    pp::panopainter::configure_legacy_slider_color_shader(mvp);
    m_plane.draw_fill();
}

void NodeSliderH::set_value(float value, bool propagate)
{
    // don't accept external values while user interaction
    if (dragging)
        return;
    m_value = value;
    if (propagate && on_value_changed)
        on_value_changed(this, m_value);
}

float NodeSliderH::get_value()
{
    return m_value;
}

void NodeSliderH::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
{
    NodeBorder::parse_attributes(ka, attr);
    switch (ka)
    {
    case kAttribute::Value:
        m_value = attr->FloatValue();
        break;
    default:
        break;
    }
}

kEventResult NodeSliderH::handle_event(Event* e)
{
    NodeBorder::handle_event(e);
    switch (e->m_type)
    {
    case kEventType::MouseDownL:
        dragging = true;
        mouse_capture();
        {
            m_old_value = m_value;
            auto sz = GetSize();
            auto pos = glm::clamp(((MouseEvent*)e)->m_pos - m_pos, { 0, 0 }, sz);
            m_value = m_comp == 0 ? 
                pos[m_comp] / glm::max(1.f, sz[m_comp]) :
                1.f - pos[m_comp] / glm::max(1.f, sz[m_comp]);
            if (on_value_changed)
                on_value_changed(this, m_value);
        }
        break;
    case kEventType::MouseUpL:
        pp::panopainter::release_legacy_mouse_capture(*this);
        if (dragging && on_value_final)
            on_value_final(this, m_value);
        dragging = false;
        break;
    case kEventType::MouseMove:
        if (dragging)
        {
            auto sz = GetSize();
            auto pos = glm::clamp(((MouseEvent*)e)->m_pos - m_pos, { 0, 0 }, sz);
            m_value = m_comp == 0 ?
                pos[m_comp] / glm::max(1.f, sz[m_comp]) :
                1.f - pos[m_comp] / glm::max(1.f, sz[m_comp]);
            if (on_value_changed)
                on_value_changed(this, m_value);
        }
        break;
    case kEventType::MouseCancel:
        pp::panopainter::release_legacy_mouse_capture(*this);
        if (dragging)
        {
            m_value = m_old_value;
            set_value(m_value);
            if (on_value_changed)
                on_value_changed(this, m_value);
        }
        dragging = false;
        break;
    default:
        return kEventResult::Available;
        break;
    }
    return kEventResult::Consumed;
}

Node* NodeSliderHue::clone_instantiate() const
{
    return new NodeSliderHue();
}

void NodeSliderHue::clone_finalize(Node* dest) const
{
    NodeSliderV::clone_finalize(dest);
    NodeSliderHue* n = static_cast<NodeSliderHue*>(dest);
    n->init_controls();
}

void NodeSliderHue::init()
{
    NodeSliderV::init();
    init_controls();
}

void NodeSliderHue::init_controls()
{
    on_value_changed = [this](Node*, float value) {
        m_color = glm::vec4(convert_hsv2rgb({ value, 1, 1 }), 1);
        if (on_hue_changed)
            on_hue_changed(this, m_color);
    };
}

glm::vec4 NodeSliderHue::get_hue()
{
    m_color = glm::vec4(convert_hsv2rgb({ m_value, 1, 1 }), 1);
    return m_color;
}

void NodeSliderHue::draw()
{
    pp::panopainter::configure_legacy_slider_hue_shader(
        m_mvp * glm::scale(glm::vec3(1, -1, 1)),
        m_comp);
    m_plane.draw_fill();
    NodeBorder::m_color = glm::vec4(0);
    NodeSliderH::draw();
}
