 
/*
 * Userspace program that communicates with the viewtube device driver
 * through ioctls
 *
 * Original by
 * Stephen A. Edwards
 * Columbia University
 *
 * Adapted by Benjamin Allison (bja2142)
 */

#include <stdio.h>
#include <linux/types.h>
#include "viewtube_kmod.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#include <stdlib.h>


#define WINDOW_DIR_UP    0
#define WINDOW_DIR_LEFT  1
#define WINDOW_DIR_RIGHT 2
#define WINDOW_DIR_DOWN  3

#define WINDOW_Y_MOVE_INTERVAL 10
#define WINDOW_X_MOVE_INTERVAL 15

#define GRAPHIC_WIDTH 1500
#define GRAPHIC_HEIGHT 1814

#define WINDOW_WIDTH  500
#define WINDOW_HEIGHT 425

#define RIGHT_WALL (GRAPHIC_WIDTH - WINDOW_WIDTH -1)
#define VERTICAL_FLOOR (GRAPHIC_HEIGHT - WINDOW_HEIGHT -1)

int viewtube_fd;

viewtube_background_window_position_t vla;


static unsigned short vt_kmod_lib_ushort_min(unsigned short left, unsigned short right)
{
  if (left > right) return right;
  return left;
}

static unsigned short vt_kmod_lib_ushort_max(unsigned short left, unsigned short right)
{
  if (left > right) return left;
  return right;
}

static unsigned short vt_kmod_lib_decrease(unsigned short original, unsigned short interval, unsigned short bound)
{
  if ( (unsigned short) (original - interval) > original)
  {
    return bound;
  }
  return vt_kmod_lib_ushort_max(original - interval,bound);
}

static unsigned short vt_kmod_lib_increase(unsigned short original, unsigned short interval, unsigned short bound)
{
  if ( (unsigned short) (original + interval) < original)
  {
    return bound;
  }
  return vt_kmod_lib_ushort_min(original + interval,bound);
}


/* Set x,y position of window into background*/
void set_viewtube_background_position(unsigned short x, unsigned short y,unsigned char bounce)
{
  vla.coordinate_x = x;
  vla.bounce = bounce;
  if (ioctl(viewtube_fd, VIEWTUBE_SET_BACKGROUND_POS_X, &vla)) {
      printf("ioctl(VIEWTUBE_SET_BACKGROUND_POS_X) failed\n");
      return;
  }
  vla.coordinate_y = y;
  if (ioctl(viewtube_fd, VIEWTUBE_SET_BACKGROUND_POS_Y, &vla)) {
      printf("ioctl(VIEWTUBE_SET_BACKGROUND_POS_Y) failed\n");
      return;
  }
}

void set_viewtube_sprite_data(viewtube_sprite_t * sprite)
{
  if (ioctl(viewtube_fd, VIEWTUBE_UPDATE_SPRITE_AT_INDEX, sprite)) {
      printf("ioctl(VIEWTUBE_UPDATE_SPRITE_AT_INDEX) failed\n");
      return;
  }
  usleep(1000);
}

void set_viewtube_sprite_pos(viewtube_sprite_t * sprite)
{
  if (ioctl(viewtube_fd, VIEWTUBE_MOVE_SPRITE_TO_NEW_POS, sprite)) {
      printf("ioctl(VIEWTUBE_MOVE_SPRITE_TO_NEW_POS) failed\n");
      return;
  }
  usleep(1000);
}

void poll_background_position(viewtube_background_window_position_t * position)
{
  if (ioctl(viewtube_fd, VIEWTUBE_GET_BACKGROUND_POS, &vla)) {
      printf("ioctl(VGA_BALL_GET_POS) failed\n");
      return;
  }
  printf("cur x/y:(%d,%d)\n",vla.coordinate_x,vla.coordinate_y);
  if(position!= NULL)
  {
    position->coordinate_x = vla.coordinate_x;
    position->coordinate_y = vla.coordinate_y;
  }
}


/* Set x,y position of window into background*/
void move_viewtube_background_position_direction(unsigned char direction, unsigned short interval)
{

  poll_background_position(NULL);
  vla.bounce = 0;
  if(WINDOW_DIR_UP == direction)
  {
    vla.coordinate_y = vt_kmod_lib_decrease(vla.coordinate_y, interval, 0);
    if (ioctl(viewtube_fd, VIEWTUBE_SET_BACKGROUND_POS_Y, &vla)) {
        printf("ioctl(VIEWTUBE_SET_BACKGROUND_POS_Y) failed\n");
        return;
    }
  } 
  else if (WINDOW_DIR_DOWN == direction)
  {
    vla.coordinate_y = vt_kmod_lib_increase(vla.coordinate_y, interval, VERTICAL_FLOOR);
    if (ioctl(viewtube_fd, VIEWTUBE_SET_BACKGROUND_POS_Y, &vla)) {
        printf("ioctl(VIEWTUBE_SET_BACKGROUND_POS_Y) failed\n");
        return;
    }
  }
  else if (WINDOW_DIR_LEFT == direction)
  {
    vla.coordinate_x = vt_kmod_lib_decrease(vla.coordinate_x, interval, 0);
    if (ioctl(viewtube_fd, VIEWTUBE_SET_BACKGROUND_POS_X, &vla)) {
        printf("ioctl(VIEWTUBE_SET_BACKGROUND_POS_X) failed\n");
        return;
    }
  }
  else if (WINDOW_DIR_RIGHT == direction)
  {
    vla.coordinate_x = vt_kmod_lib_increase(vla.coordinate_x, interval, RIGHT_WALL);
    
    if (ioctl(viewtube_fd, VIEWTUBE_SET_BACKGROUND_POS_X, &vla)) {
        printf("ioctl(VIEWTUBE_SET_BACKGROUND_POS_X) failed\n");
        return;
    }
  }
}

