#include "WaylandPointerInterface.h"

#include "FileLogger.h"

static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
{

}

static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source)
{

}

static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis)
{

}

static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete)
{

}

WaylandPointerInterface::~WaylandPointerInterface()
{
    wl_pointer_release(mPointer);
}

void WaylandPointerInterface::pointerFrameEvent(void *data, struct wl_pointer *wl_pointer)
{
    auto thisClass = static_cast<WaylandPointerInterface*>(data);
    thisClass->onPointerFrame();
}

void WaylandPointerInterface::pointerEnterEvent(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
    auto thisClass = static_cast<WaylandPointerInterface*>(data);
    thisClass->onPointerEnter(serial, surface, surface_x, surface_y);
}

void WaylandPointerInterface::pointerLeaveEvent(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface)
{
    auto thisClass = static_cast<WaylandPointerInterface*>(data);
    thisClass->onPointerLeave(serial);
}

void WaylandPointerInterface::pointerMotionEvent(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
    auto thisClass = static_cast<WaylandPointerInterface*>(data);
    thisClass->onPointerMotion(time, surface_x, surface_y);
}

void WaylandPointerInterface::pointerButtonEvent(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
{
    auto thisClass = static_cast<WaylandPointerInterface*>(data);
    thisClass->onPointerButton(serial, time, button, state);
}

void WaylandPointerInterface::onPointerFrame()
{
    if (mWorkingPointerEvent.event_mask & POINTER_EVENT_ENTER)
    {
        const auto locx = wl_fixed_to_double(mWorkingPointerEvent.surface_x);
        const auto locy = wl_fixed_to_double(mWorkingPointerEvent.surface_y);
    }
    else if (mWorkingPointerEvent.event_mask & POINTER_EVENT_LEAVE)
    {

    }
    else if (mWorkingPointerEvent.event_mask & POINTER_EVENT_MOTION)
    {

    }
    else if (mWorkingPointerEvent.event_mask & POINTER_EVENT_BUTTON)
    {
        const bool released = mWorkingPointerEvent.state == WL_POINTER_BUTTON_STATE_RELEASED;
    }
    mWorkingPointerEvent = WaylandPointerEvent();
}

void WaylandPointerInterface::onPointerButton(uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
{
    mWorkingPointerEvent.event_mask |= POINTER_EVENT_BUTTON;
    mWorkingPointerEvent.time = time;
    mWorkingPointerEvent.serial = serial;
    mWorkingPointerEvent.button = button;
    mWorkingPointerEvent.state = state;
}

void WaylandPointerInterface::onPointerEnter(uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
    mWorkingPointerEvent.event_mask |= POINTER_EVENT_ENTER;
    mWorkingPointerEvent.serial = serial;
    mWorkingPointerEvent.surface_x = surface_x;
    mWorkingPointerEvent.surface_y = surface_y;
}

void WaylandPointerInterface::onPointerLeave(uint32_t serial)
{
    mWorkingPointerEvent.event_mask |= POINTER_EVENT_LEAVE;
    mWorkingPointerEvent.serial = serial;
}

void WaylandPointerInterface::onPointerMotion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
    mWorkingPointerEvent.event_mask |= POINTER_EVENT_MOTION;
    mWorkingPointerEvent.time = time;
    mWorkingPointerEvent.surface_x = surface_x;
    mWorkingPointerEvent.surface_y = surface_y;
}

WaylandPointerInterface::WaylandPointerInterface(wl_pointer* pointer)
    : mPointer(pointer)
{
    mPointerListener.enter = pointerEnterEvent;
    mPointerListener.leave = pointerLeaveEvent;
    mPointerListener.button = pointerButtonEvent;
    mPointerListener.motion = pointerMotionEvent;
    mPointerListener.axis = wl_pointer_axis;
    mPointerListener.axis_discrete = wl_pointer_axis_discrete;
    mPointerListener.axis_source = wl_pointer_axis_source;
    mPointerListener.axis_stop = wl_pointer_axis_stop;
    mPointerListener.frame = pointerFrameEvent;

    wl_pointer_add_listener(mPointer, &mPointerListener, this);
}
