#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <math.h>

#define PI 3.14159265359879323846

const int FRAMERATE = 2000; /* frame rate in microseconds */
const int SCREEN_ROWS = 24;
const int SCREEN_COLS = 80;
const int MAX_ROW = SCREEN_ROWS-5; 
const int MAX_COL = SCREEN_COLS-9;
const double THETA = PI/4;
const double T = .01;

double X0 = 0;
double Y0 = 13;
double V0 = 1.3;
double F = .1;
double g = -2.98;

bool end = false;
bool sound = false;

void beep();
void erase_all();
void position (int row,int  column);
int u_sleep(unsigned int usec); /* sleep for specified number of microsecs */
void print_ball(int row, int col);
void find_position(int& row, int& col, double& t);

int main (int argc, char *argv[])
{

  extern int optind;
  extern int opterr;
  optarg = NULL;
  int opt;
  int errflg = 0;
  int count = 0;

  double t = 0;
  int row, col;

  if (argc > 1) {
    while ((opt = getopt(argc, argv, "v:b")) != EOF) {
      switch (opt) {
      case 'v':
	V0 = atof(optarg);
	if (V0 < 0 || V0 > 10.0) {
	  fprintf (stderr, "Please specify a velocity between 0 and 10.0\n");
	  exit(2);
	}
	break;
      case 'b':
	sound = true;
	break;
      default:
	errflg++;
      }
    }
    if (errflg) {
      fprintf (stderr, "Usage: ball [-b][-v velocity]\n");
      exit (2);
    } 

  }
    
  for ( ; optind < argc; optind++) {
    count++;
    if (count > 0) {
      printf ("ball: Too many arguments.\n");
      exit (2);
    }
  }

  while (!end) {
    erase_all();
    find_position(row, col, t);
    print_ball(row, col);
    u_sleep(FRAMERATE);
    t+=T;
  }
}

void find_position(int& row, int& col, double& t)
{
  static double px = X0;
  static double py = Y0;
  static double vy = V0*sin(THETA);
  static double vx = V0*cos(THETA);

  vy = vy + g*T;
  px = px + vx;
  py = py + vy;

  row = (int) py;
  col = (int) px;
  
  if (py <= 0 || py >= MAX_ROW) {
    if (vy != 0) {
      if (vy < F && vy > -F) {
            vy = 0;
      } else {
	vy = vy > 0 ? vy-F : vy+F;
            vy = -vy;
      }
    }
  }
  if (px <= 0 || px >= MAX_COL) {
    if (vx != 0) {
      if (vx < F && vx > -F) {
            vx = 0;
      } else {
	vx = vx > 0 ? vx-F : vx+F;
            vx = -vx;
      }
    }
  }
      
  if (px > MAX_COL) {
        px = MAX_COL;
  } else if (px < 0) {
        px = 0;
  }
      
  if (py > MAX_ROW) {
        py = MAX_ROW;
  } else if (py < 0) {
        py = 0;
  }

  /*

  if (row <= 0 || row >=MAX_ROW) {
    vy-=F;
    if (vy != 0) {
      
    if (vx >= .001) {
      vx-=.001;
    } else {
      vx = 0;
    }
    vy = -vy;
    }
  */
}

void print_ball(int row, int col)
{
  static int stationary = 0;
  int i;
  col = col % SCREEN_COLS + 1;
  

  if (row<=0) {
    stationary++;
    if (stationary > 10) {
      end = true;
    }
    if (stationary==1 && sound) {
      beep();
    }
  } else {
    stationary = 0;
  }

  if (row < 0) {
    row = 0;
  }
  if (row > MAX_ROW) {
    row = MAX_ROW;
  }
  row = MAX_ROW-row;
    
  position(row, col);
  printf("  .LLII:.\n");
  position(row+1, col);
  printf(" ANEFLI::.\n");
  position(row+2, col);
  printf(" NMARYLLI:\n");
  position(row+3, col);
  printf(" VWWNNHEF+\n");
  position(row+4, col);
  printf("  `VWWWV'\n"); 
  
  position(SCREEN_ROWS, 0);
  for (i=0; i < SCREEN_COLS; i++) {
    printf("-");
  }
  printf("\n");
}

int u_sleep(unsigned int usec)
{
  static int subtotal = 0;
  int msec;

  struct pollfd foo;

  subtotal += usec;
  if (subtotal < 1000) return (0);
  msec = subtotal/1000;
  subtotal = subtotal%1000;
  return poll(&foo,(unsigned long)0, msec);

}



void position (int row,int  column)
{
  printf("\033[H\033[%d;%dH", row, column);

}


void erase_all()
{
  printf("\033[2J");
}

void beep()
{
  printf("\007");
}


