#include <stdio.h>
#include <stdlib.h>
#include "egui.h"
#include "mouse.h"

static char *mmouse_cursor_default = {
"..##############"
".a..############"
".aaa.###########"
".aaaa..#########"
".aaaaaa.########"
".aaaaaaa.#######"
".aaaaaaaa.######"
".aaaaaa..#######"
".aaaaa.#########"
".aaaaaa.########"
".aa..aaa.#######"
".a.##.aa.#######"
"..###.aaa.######"
"######.aaa.#####"
"#######.a.######"
"########.#######"};

static char *mmouse_cursor;
static char *mmouse_under_cursor;

int mmouse_x,mmouse_y, mmouse_ox,mmouse_oy,mmouse_ol,mmouse_or;

static int mmouse_visible;

//==============================================================================

void mouse_drawmouse() {
  int dx, dy,mult;
  char *mac = mmouse_cursor;
  
  if (mmouse_x>=320) mult=-1;
  else mult=1;

  for (dy=0;dy<16;dy++) {
    for (dx=0;dx<16;dx++) {
      if ( *mac != '#' ) {
        if ( *mac=='.' ) vga_setcolor(0);
	else vga_setcolor(255);
        vga_drawpixel(mmouse_x+(dx*mult),mmouse_y+(dy)); 
      }
      mac++;
    }
  }
}

//==============================================================================

void mouse_getmouse() {
  int dx, dy,mult;
  char *mac = mmouse_under_cursor;
  
  if (mmouse_x>=320) mult=-1;
  else mult=1;

  for (dy=0;dy<16;dy++) {
    for (dx=0;dx<16;dx++) {
      *mac++=vga_getpixel(mmouse_x+(dx*mult),mmouse_y+(dy));
    }
  }
}

//==============================================================================

void mouse_undrawmouse() {
  int dx, dy,mult;
  char *mac = mmouse_under_cursor;
  
  if (mmouse_ox>=320) mult=-1;
  else mult=1;
  
  for (dy=0;dy<16;dy++) {
    for (dx=0;dx<16;dx++) {
      vga_setcolor(*mac++);
      vga_drawpixel(mmouse_ox+(dx*mult),mmouse_oy+(dy)); 
    }
  }
}

//==============================================================================

void mmouse_hide() {
  int dx, dy,mult;
  char *mac = mmouse_under_cursor;
  
  if (!mmouse_visible) return;

  mmouse_visible=0;

  if (mmouse_x>=320) mult=-1;
  else mult=1;
  
  for (dy=0;dy<16;dy++) {
    for (dx=0;dx<16;dx++) {
      vga_setcolor(*mac++);
      vga_drawpixel(mmouse_x+(dx*mult),mmouse_y+(dy)); 
    }
  }
}

//==============================================================================

void mmouse_show() {
  if (mmouse_visible) return;
  mouse_getmouse();
  mouse_drawmouse();
  mmouse_visible=1;
}

//==============================================================================

int mmouse_detect() {
  int mt;

  printf("Initializing Mouse\n");
  mt=vga_getmousetype()&&MOUSE_TYPE_MASK;
  printf("  Found ");
  switch(mt) {
    case MOUSE_NONE:
      printf("No Mouse\n");
      break;
    case MOUSE_MICROSOFT:
      printf("a Generic serial mouse\n");
      break;
    case MOUSE_MOUSESYSTEMS:
      printf("a MouseSystems compatible mouse\n");
      break;
    case MOUSE_MMSERIES:
      printf("an MMSeries compatible mouse\n");
      break;
    case MOUSE_LOGITECH:
      printf("a LogiTech compatible mouse\n");
      break;
    case MOUSE_BUSMOUSE:
      printf("a busmouse\n");
      break;
    case MOUSE_PS2:
      printf("a PS/2 mouse\n");
      break;
    case MOUSE_LOGIMAN:
      printf("a LogiTech LogiMan mouse\n");
      break;
    case MOUSE_GPM:
      printf("GPM mouse daemon\n");
      break;
    case MOUSE_SPACEBALL:
      printf("a 3D SpaceTech SpaceBall pointer device\n");
      break;
    case MOUSE_INTELLIMOUSE:
      printf("a Logitech MouseMan+ on serial port\n");
      break;
    case MOUSE_IMPS2:
      printf("a Logitech MouseMan+ on PS/2 port\n");
      break;
    default:
      printf("Unknown Mouse Type (%d)\n",mt);
  }
  if ( (mt)==MOUSE_NONE ) {
    return 0;
  }
  return 1;
}

//==============================================================================

void mmouse_handler(int button, int  dx,  int
       dy,  int dz , int drx, int dry, int drz) {
       
  int but_l,but_r;   

  if ((dx)||(dy)) {
    mmouse_ox=mmouse_x;
    mmouse_oy=mmouse_y;
    mmouse_x+=dx;
    if (mmouse_x<0) mmouse_x=0;
    if (mmouse_x>639) mmouse_x=639;
    mmouse_y+=dy;
    if (mmouse_y<0) mmouse_y=0;
    if (mmouse_y>479) mmouse_y=479;
    if (mmouse_visible) {
      mouse_undrawmouse();
      mouse_getmouse();
      mouse_drawmouse();
    }  
    egui_Event_Add(EGUI_EVENT_MOUSE_MOVEMENT,mmouse_x, mmouse_y, 0, NULL, NULL);
  };
  
  but_l=(button&MOUSE_LEFTBUTTON);
  but_r=(button&MOUSE_RIGHTBUTTON);
  if (but_l!=mmouse_ol) {
    if (but_l&MOUSE_LEFTBUTTON) {
      egui_Event_Add(EGUI_EVENT_MOUSE_LEFT_PRESSED,mmouse_x, mmouse_y,0 , NULL, NULL); }
    else {
      egui_Event_Add(EGUI_EVENT_MOUSE_LEFT_RELEASED,mmouse_x, mmouse_y,0 , NULL, NULL);
    };
    mmouse_ol=but_l;
  }
  if (but_r!=mmouse_or) {    
    if (but_r&MOUSE_RIGHTBUTTON) {
      egui_Event_Add(EGUI_EVENT_MOUSE_RIGHT_PRESSED,mmouse_x, mmouse_y,0 , NULL, NULL); }
    else {
      egui_Event_Add(EGUI_EVENT_MOUSE_RIGHT_RELEASED,mmouse_x, mmouse_y,0 , NULL, NULL);
    };
    mmouse_or=but_r;
  }
}       

//==============================================================================

void mmouse_init() {
  mmouse_under_cursor=calloc(1,256);
  mmouse_cursor=mmouse_cursor_default;
  mouse_seteventhandler(mmouse_handler);
  mmouse_x=320;mmouse_y=240;
  mmouse_show();
}

//==============================================================================

void mmouse_done() {
  free(mmouse_under_cursor);
  if (mmouse_cursor!=mmouse_cursor_default) free(mmouse_cursor);
};

//==============================================================================
