
#include "swis.h"
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "Global/NewErrors.h"
#include "Global/RISCOS.h"
#include "Global/Keyboard.h"
#include "Global/Pointer.h"

#include "debugrep.h"
#include "usbjoystickHdr.h"
#include "usbjoystick.h"

#include "mouse.h"

// which joystick, if any, is performing mouse duties?
int32_t mouse_joy = NOT_MAPPED;
os_pointer_type initial_pointer_type;
int32_t mouse_rel_x = 0;
int32_t mouse_rel_y = 0;
int32_t mouse_select = 0;
int32_t mouse_menu = 0;
int32_t mouse_adjust = 0;
int32_t mouse_previous_select = 0;
int32_t mouse_previous_menu = 0;
int32_t mouse_previous_adjust = 0;
int32_t mouse_previous_pc_x = 0;
int32_t mouse_previous_pc_y = 0;


osbool pointerv_claimed = FALSE;


int32_t pointerv_hook_handler(_kernel_swi_regs *r, void *pw)
{
  IGNORE(pw);

  if (r->r[0] == PointerReason_Request && mouse_joy != NOT_MAPPED) {
    // we need to update pointer position
    int32_t irqs = _kernel_irqs_disabled();
    if (!irqs)
      _kernel_irqs_off();
    r->r[2] = mouse_rel_x;
    r->r[3] = mouse_rel_y;
    mouse_rel_x = mouse_rel_y = 0;
    if (!irqs)
      _kernel_irqs_on();
    return VECTOR_CLAIM;      // todo: is this sensible?!  we are not the only pointer device, are we?
  }

  return VECTOR_PASSON;
}


void update_mouse(uint32_t i)
{
    // get mouse x update
    struct axisdata_struct mx = joy_data[i].axes[joy_data[i].mapped_mouse_x];
    //int32_t pc_x = scaled_value_8(&mx);
    //int32_t dx = abs(pc_x-mouse_previous_pc_x) + 1;    // plus step?
    int32_t x = 0;
    if (mx.val > mx.mid)
      x = mx.mouse_factor;
    else if (mx.val < mx.mid)
      x = -mx.mouse_factor;
    if (mx.flip)
      x = x * -1;
    mouse_rel_x = mouse_rel_x + x;
    //mouse_previous_pc_x = pc_x;
    // get mouse y update
    struct axisdata_struct my = joy_data[i].axes[joy_data[i].mapped_mouse_y];
    int32_t y = 0;
    if (my.val > my.mid)
      y = -my.mouse_factor;
    else if (my.val < my.mid)
      y = my.mouse_factor;
    if (my.flip)
      y = y * -1;
    mouse_rel_y = mouse_rel_y + y;
    // update pointerv if there is pointer movement
    if (x || y) {
      // position
      _swix(OS_CallAVector, _INR(0,4) | _IN(9), PointerReason_Report, initial_pointer_type, x, y, 0, PointerV);
    }
    // select button
    if (joy_data[i].mapped_mouse_select != NOT_MAPPED) {
      int32_t select = joy_data[i].buttons[joy_data[i].mapped_mouse_select];
      osbool changed = (select != mouse_previous_select);
      mouse_previous_select = select;
      if (changed)
        _swix(OS_CallAVector, _INR(0,1) | _IN(9), (select)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_LeftMouse, KEYV);
    }
    // menu button
    if (joy_data[i].mapped_mouse_menu != NOT_MAPPED) {
      int32_t menu = joy_data[i].buttons[joy_data[i].mapped_mouse_menu];
      osbool changed = (menu != mouse_previous_menu);
      mouse_previous_menu = menu;
      if (changed)
        _swix(OS_CallAVector, _INR(0,1) | _IN(9), (menu)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_CentreMouse, KEYV);
    }
    // adjust button
    if (joy_data[i].mapped_mouse_adjust != NOT_MAPPED) {
      int32_t adjust = joy_data[i].buttons[joy_data[i].mapped_mouse_adjust];
      osbool changed = (adjust != mouse_previous_adjust);
      mouse_previous_adjust = adjust;
      if (changed)
        _swix(OS_CallAVector, _INR(0,1) | _IN(9), (adjust)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_RightMouse, KEYV);
    }
}

