#include <GLFW/glfw3.h>

#include "client/input/MouseButtons.h"

MouseButtons::MouseButton::MouseButton() : down(false), shouldRelease(false), downTime(0) {
}

bool MouseButtons::MouseButton::isDown() const {
    return down;
}

bool MouseButtons::MouseButton::isReleased() const {
    return shouldRelease;
}

u32 MouseButtons::MouseButton::getDownTime() const {
    return downTime;
}

std::ostream& operator<<(std::ostream& os, const MouseButtons::MouseButton& m) {
    os << "Mouse(down: " << m.isDown() << ", release: " << m.isReleased() <<
            ", time: " << m.getDownTime() << ")";
    return os;
}

MouseButtons::MouseButtons() : primary(buttons[0]), secondary(buttons[1]), middle(buttons[2]), lastX(0), lastY(0),
x(0), y(0), updateLast(true) {
    buttons[0].glfwButton = GLFW_MOUSE_BUTTON_1;
    buttons[1].glfwButton = GLFW_MOUSE_BUTTON_2;
    buttons[2].glfwButton = GLFW_MOUSE_BUTTON_3;
}

double MouseButtons::getLastX() const {
    return lastX;
}

double MouseButtons::getLastY() const {
    return lastY;
}

double MouseButtons::getX() const {
    return x;
}

double MouseButtons::getY() const {
    return y;
}

void MouseButtons::release(int button) {
    for(MouseButton& k : buttons) {
        if(k.glfwButton == button) {
            k.shouldRelease = true;
        }
    }
}

void MouseButtons::press(int button) {
    for(MouseButton& k : buttons) {
        if(k.glfwButton == button) {
            k.down = true;
            k.shouldRelease = false;
        }
    }
}

void MouseButtons::move(double x, double y) {
    MouseButtons::x = x;
    MouseButtons::y = y;
    updateLast = false;
}

void MouseButtons::tick() {
    if(updateLast) {
        lastX = x;
        lastY = y;
    }
    updateLast = true;
    for(MouseButton& k : buttons) {
        k.downTime += k.down;
        k.down = k.down && !k.shouldRelease;
        k.downTime *= !k.shouldRelease;
        k.shouldRelease = false;
    }
}