//////////////////////////////////////////////////////////////////////
// Program to test the operation of a joystick
//				(a distant offspring of js_demo)
//
// Typical usage:  js_test
//
// First, we print the names (and busID numbers) of all the 
// connected joysticks.  
// Then we loop, displaying the readings from all the axes
// and all the buttons on the *first* joystick that is
// connected and working.
//
// Fancy usage:  js_test ID
//	where ID is the busID number of the joystick you
//	want to look at.  We look at that one, regardless
//	of whether it is first in the list or not.  We
//	display the readings in the usual way.
//
// Here is a typical display of readings.  There are two rows:
//
// Ax:00 Ax:01 Ax:02 Ax:03 Ax:04 Ax:05 Ax:06 Ax:07 Ax:08 Ax:09 Ax:10  32 24 16  8  0
// +0.00 +0.00 +1.00 +1.00 +1.00 +0.00 -1.00 +0.00 +0.00 +0.14 +0.14  00 02 00 0a 00 

// The first row is a bunch of column headers.
// The actual readings appear in the second row. 

// The header Ax:00 refers to axis #0 and Ax:10 refers to axis #10.

// To the right of the axis columns are the button colums.
// The buttons are grouped in groups of 8, and represented
// by two hex digits per byte.  The column header indicates
// the bit-number of the lowest-order bit in the byte.
// In this example, bits 9, 11, and 25 are shown as being "set".

// We are limited to testing one joystick at a time, so if you 
// have more than one, you will have to take turns testing them.
//
// This limitation is because we are too lazy to use curses.
// We simply use \r to overwrite the line of readings.
// Extending this to use curses would be straightforward.

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#ifdef HAVE_WINDOWS_H
#  include <windows.h>                     
#endif

#include <plib/js.h>

#define Z 8		/* Number of possible joystick devices */

int to8(const v_bool& bbb, const int offset){
  int rslt(0);
  int walker(1);
  int lim(offset+8);
  if (lim > bbb.size()) lim = bbb.size();
  for (int ii = offset; ii < lim; ii++){
    if (bbb[ii]) rslt |= walker;
    walker <<= 1;
  }
  return rslt;
}

void dump_names(jsJoystick * js[], const int lookat) {
  for (int i = 0; i < Z; i++ ) {
    int useful = ! ( js[i]->notWorking () );
    if ( useful ) {
	printf ( "Joystick %i: '%s'", i, js[i]->getName() ) ;
    } else {
      printf ( "Joystick %i not detected", i ) ;
    }
    if (i == lookat) printf (" <<<<<<< ");
    printf ("\n");

  }
}

int main ( int argc, char ** argv )
{
  printf ( "Joystick test program.\n" ) ;
  printf ( "~~~~~~~~~~~~~~~~~~~~~~\n" ) ;

  int lookat(-1);

  if (argc > 1) lookat = atoi(argv[1]);

  jsJoystick *js[Z] ;
  int j, useful[Z];

  jsInit();

  for (int i = 0; i < Z; i++ )
      js[i] = new jsJoystick ( i ) ;

  if (lookat < 0) {
  // Loop over all possible device numbers.
  // Make a note of the first one that works.

    for (int i = 0; i < Z; i++ )
    { 
      useful[i] = ! ( js[i]->notWorking () );
      if (useful[i] && lookat < 0) {
        lookat = i;
      }
    }

    dump_names(js, lookat);
  }

  if ( lookat < 0 ) {
    fprintf(stderr, "Couldn't find any working joysticks\n");
    exit ( 1 ) ;
  }
  
  if (js[lookat]->notWorking() ) {
    fprintf(stderr, "ID %d isn't a working joystick\n", lookat);
    dump_names(js, lookat);
    exit ( 1 ) ;
  }
  

  int button_bytes(0);

  printf (" ");

  for ( j = 0 ; j < js[lookat]->getNumAxes () ; j++ ) {
    printf ( "Ax:%02d ", j ) ;
  }

  button_bytes = (js[lookat]->getNumButtons() + 7)/8;
  for (int pos = button_bytes-1; pos>=0; pos--){
    printf("%3d", pos*8);
  }

  printf ( "\n" ) ;	// end of column-header line

  if (0)  for (int ii = 40-1; ii>=0; ii--){
      int jj = ii % 10;
      printf("%1d", jj);
    }

// loop forever, updating the results line.
  while (1) {
    printf (" ");


   if ( js[lookat]->notWorking () ) {
     printf ("\n");
     printf ("Stopped working\n");
// should maybe investigate why it stopped working?
     exit (2);
   }


   v_bool b;
   v_float ax;

   js[lookat]->read ( b, ax ) ;

   for ( j = 0 ; j < js[lookat]->getNumAxes () ; j++ )
     printf ( "%+.2f ", ax[j] ) ;

// print the button-bits
   printf (" ");
   for (int pos = button_bytes-1; pos>=0; pos--){
     int tmp = to8(b, pos*8);
     printf("%02x ", tmp);
   }

   printf ( "\r" ) ;
   fflush ( stdout ) ;

   /* give other processes a chance */

#ifdef WIN32
    Sleep ( 1 ) ;
#elif defined(sgi)
    sginap ( 1 ) ;
#else
    usleep ( 1000 ) ;
#endif
  }

// I don't think we ever get here

  return 0 ;
}


