/****************************************************************************/
/* Copyright (c) 2001 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Author   : Rich Henthorn                                                 */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 05 Jun 01                                                     */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <i86.h>
#include <signal.h>
#include <process.h>
#include <time.h>

#include "BuoyLauncherIF.h"
#include "BuoyLauncherInput.h"
#include "BuoyLauncherMsgs.h"
#include "Syslog.h"
#include "System.h"
#include "SerialParameters.h"

void printStat(BuoyLauncherIF::LC_status stat)
{
  printf("\t**** Launcher Status Record from %s",
	 asctime(localtime(&stat.timeSec)));
  printf("LC Error: %d\t\tLast Launch OK: %d\tBuoy Responsive: %d\n",
	 stat.launcherError, stat.lastLaunchOK, stat.buoyResponsive);
  printf("Next Buoy Ready: %d\tCurrent Buoy#: %d\tTotal # Buoys: %d\n",
	 stat.nextBuoyReady, stat.currentBuoyNumber, stat.numTotalBuoys);
  printf("Remain Buoys: %d\tBuoys Launched: %d\n",
	 stat.numBuoysRemain, stat.numBuoysLaunched);
  printf("ARGOS Loaded: %ld\tARGOS Left: %ld\n",
	 stat.argosBytes, stat.dataMemory);
  printf("Archive Loaded: %ld\tArchive Left: %ld\n",
	 stat.archiveBytes, stat.picoBytes);
}

int main( int argc, char **argv ) 
{
  BuoyLauncherIF *buoyLauncherIF;

  pid_t _serverPid;
  pid_t workSiteServer;

#if 0
  if ((workSiteServer = System::spawn("workSite",  "")) == -1) 
    throw Exception("System::spawn(workSite Server) failed");

  printf(" buoyLauncherTest: Started WorkSite Server.\n");
#endif

  if (argc < 4)
  {
    Syslog::write("Test::invalid argument list");
    printf("Usage: buoyLauncherTest commands serial_spec_type serial_spec\n");
    printf("\tcommands - single string of single letter commands\n");
    printf("\tserial_spec_type - either \"-dev\" or \"-serial\"\n");
    printf("\tserial_spec - serial line parameters based on the spec type\n");
  }

  try 
  { 
    SerialParameters serialParams(&argc, argv);
    char argString[100];
    sprintf(argString, "-serial %s", serialParams.string());
    if ((_serverPid = System::spawn("buoyLauncherServer", argString)) == -1)
      {
	Syslog::write("System::spawn(buoyLauncherServer) failed\n");
	exit( -1 );
      }
  }
  catch ( ... )
  {
    Syslog::write("buoyLauncherTest -- "
		  "caught exception on spawning of BuoyLauncher Server\n");
    exit( -1 );
  }

  try 
  {
    buoyLauncherIF = new BuoyLauncherIF( "BLS", 1000 );
  }
  catch (...)
  {
    Syslog::write("_buoyLauncherTest -- Caught exception on IF creation\n");
    exit( -1 );
  }


  BuoyLauncherIF::LC_status lc_stat;
  BuoyLauncherIF::Filename datafile;
  //strcpy(datafile, "/usr/include/form.h");
  strcpy(datafile, "/usr/bin/elvis");
  //strcpy(datafile, "./test.src");

  Boolean commandFinished = True;
  char *commands = argv[1];
  char thisCmd = '\0';
  int count = 0, clen = strlen(commands);
  Boolean testTimeout = False;
  time_t now, start = time((long*)0);
  int buoynum;
  int nminutes;

  delay(3500); // Let LC get up to speed

  for (int ii = 0; ii < clen /*&& !testTimeout*/; )
  {
    delay(1500);

    // If I'm still waiting for a command to finish, check to see
    // if it is finished now.
    //
    if (!commandFinished)
    {
      printf("Test: checking for the completion of the %c cmd\r",thisCmd);
      switch (thisCmd)
      {
      case '\0':
	commandFinished = True;
	break;

      case LAUNCH_REAL_HOT:
      case LAUNCH_REAL_COLD:
	buoyLauncherIF->getLauncherStatus(&lc_stat);

	if (lc_stat.lastLaunchDone)
	{
	  commandFinished = True;
	  if (lc_stat.lastLaunchOK)
	    Syslog::write("\t** Test:Launch Buoy: successful! **");
	  else
	  {
	    Syslog::write("\t** Test:Launch Buoy: UNsuccessful! **");
	    if (lc_stat.launcherError == NO_BUOY_AT_LAUNCH_POS)
	      Syslog::write("Try inserting \"N%dR%c\"", buoynum, thisCmd);
	  }

	  if (lc_stat.armsRetracted)
	    Syslog::write("\t** Test:Launch Buoy: arms retracted! **");
	  else
	    Syslog::write("\t** Test:Launch Buoy: arms NOT retracted! **");
	}
	break;

      case PUSH_OUT_RETRACT:
      case RETRACT_LARMS:
	if (buoyLauncherIF->ready())
	{
	  buoyLauncherIF->getLauncherStatus(&lc_stat);
	  commandFinished = True;

	  if (lc_stat.armsRetracted)
	  {
	    Syslog::write("\t** Test: arms retracted! **");
	  }
	  else
	    Syslog::write("\t** Test: arms NOT retracted! **");
	}
	break;

      case LAUNCH_FAKE:
	if (buoyLauncherIF->ready())
	{
	  commandFinished = True;
	  buoyLauncherIF->getLauncherStatus(&lc_stat);
	  if (lc_stat.lastLaunchOK)
	    Syslog::write("\t** Test:Launch Fake: successful! **");
	  else
	    Syslog::write("\t** Test:Launch Fake: UNsuccessful! **");
	}
	break;

      case UPLOAD_LC_LOG:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test:Upload Log: Launcher log file uploaded **");
	  commandFinished = True;
	}

	break;

      case REINITIALIZE:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test: Reinitialize process complete **");
	  commandFinished = True;
	}

	break;

      case ROTATE_BUOY:
	if (!buoyLauncherIF->ready())
	  break;

	buoyLauncherIF->getLauncherStatus(&lc_stat);
	if (lc_stat.buoyResponsive)
	{
	  Syslog::write("\t** Test:Rotate Buoy:Mr. Good buoy in position **");
	  commandFinished = True;
	}
	else if (lc_stat.numBuoysRemain == 0)
	{
	  Syslog::write("\t** Test:Rotate Buoy:No good buoys found **");
	  commandFinished = True;
	}
	else
	{
	  Syslog::write("\t** Test:Rotate Buoy: cmd timed-out **");
	  commandFinished = True;
	}
	break;

      case ROTATE_LAUNCH_POS:
      case ROTATE_DATA_POS:
      case ROTATE_CARO:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test:Rotate Carousel: done **");
	  commandFinished = True;
	}
	break;

      case XFER_ARCHIVE:
	if (buoyLauncherIF->ready())
	{
 	  Syslog::write("\t** Test:Data transfer: complete **");
	  commandFinished = True;
        }
	break;

      case XFER_ARGOS:
	if (buoyLauncherIF->ready())
	{
	  buoyLauncherIF->getLauncherStatus(&lc_stat);
	  if (lc_stat.nextBuoyReady)
	  {
	    Syslog::write("\t** Test:Data transfer: complete **");
	    commandFinished = True;
	  }
	}
	break;

      case CURRENT_BUOY:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test:Current Buoy: complete **");
	  commandFinished = True;
	}
	break;

      case LC_STATUS:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test:Get Status: complete **");
	  commandFinished = True;
	}
	break;

      case LCBC_STATUS:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test:Get Status: complete **");
	  commandFinished = True;
	}
	break;

      case STATUS_ON:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test:Status calls on: complete **");
	  commandFinished = True;
	}
	break;

      case STATUS_OFF:
	if (buoyLauncherIF->ready())
	{
	  Syslog::write("\t** Test:Status calls off: complete **");
	  commandFinished = True;
	}
	break;

      default:
	Syslog::write("Unknown command: %c", thisCmd);
	commandFinished = True;
	break;
      }

      if (!commandFinished)
	continue;   // Continue checking thisCmd
      else
      {
	sleep(2);
	ii++;       // Go on to the next one
      }
    }

    // Must be finished with the last command, so do the next one
    //
    if (!buoyLauncherIF->ready())
      continue;

    thisCmd = commands[ii];
    Syslog::write("Test: executing %c command", thisCmd);
    switch (thisCmd)
    {
    case WAKEUP:
      Syslog::write("Command %c cannot be executed through %s", thisCmd,
		    "the Buoy Launcher Server");
      ii++;   // Just go to the next command
      break;

    case SET_TIME:
      Syslog::write("Command %c cannot be executed through %s", thisCmd,
		    "the Buoy Launcher Server");
      ii++;   // Just go to the next command
      break;

    case LAUNCH_REAL_HOT:
    case LAUNCH_REAL_COLD:
      buoyLauncherIF->getLauncherStatus(&lc_stat);
      if (lc_stat.buoyResponsive && lc_stat.nextBuoyReady)
      {
	buoynum = lc_stat.currentBuoyNumber;
	if (DeviceIF::Ok == buoyLauncherIF->launch(thisCmd))
	  commandFinished = False;
      }
      else
      {
	Syslog::write("Test::Launch Buoy: Buoy not responsive");
	if (++count > 50)
	{
	  count = 0;
	  ii++; //skip
	}
      }
      break;

    case LAUNCH_FAKE:
      if (DeviceIF::Ok == buoyLauncherIF->launchDummyBuoy())
	commandFinished = False;
      break;

    case UPLOAD_LC_LOG:
      if (commands[ii+1] < '0' || commands[ii+1] > '9')
      {
	Syslog::write("Character following a 'U' in the command string %s",
		      "must be between 1-9 inclusive");
	break;
      }
      for (nminutes = 0; commands[ii+1] >= '0' && commands[ii+1] <= '9'; ii++)
	nminutes = nminutes*10 + (commands[ii+1] - '0');

      if (DeviceIF::Ok == buoyLauncherIF->uploadLog(nminutes))
	commandFinished = False;
      break;

    case ROTATE_BUOY:
      if (DeviceIF::Ok == buoyLauncherIF->rotateBuoy())
	commandFinished = False;
      break;

    case ROTATE_CARO:
      if (DeviceIF::Ok == buoyLauncherIF->rotateCarousel())
	commandFinished = False;
      break;

    case PUSH_OUT_RETRACT:
      if (DeviceIF::Ok == buoyLauncherIF->pushAndRetract())
	commandFinished = False;
      break;

    case RETRACT_LARMS:
      if (DeviceIF::Ok == buoyLauncherIF->retractArms())
	commandFinished = False;
      break;

    case REINITIALIZE:
      if (DeviceIF::Ok == buoyLauncherIF->reinitLauncher())
	commandFinished = False;
      break;

    case ROTATE_LAUNCH_POS:
    case ROTATE_DATA_POS:
      if (DeviceIF::Ok == buoyLauncherIF->rotateAPosition(thisCmd))
	commandFinished = False;
      break;

    case XFER_ARGOS:
      buoyLauncherIF->statusOn(False);
      if (DeviceIF::Ok == buoyLauncherIF->loadData(datafile, 'X'))
	commandFinished = False;

      buoyLauncherIF->statusOn(True);

      break;

    case XFER_ARCHIVE:
      buoyLauncherIF->statusOn(False);
      if (DeviceIF::Ok == buoyLauncherIF->loadData(datafile, 'D'))
	commandFinished = False;

      buoyLauncherIF->statusOn(True);

      break;

    case CURRENT_BUOY:
      if (commands[ii+1] < '1' || commands[ii+1] > '9')
      {
	Syslog::write("Character following a 'N' in the command string %s",
		      "must be between 1-9 inclusive");
	break;
      }
      for (buoynum = 0; commands[ii+1] >= '0' && commands[ii+1] <= '9'; ii++)
	buoynum = buoynum*10 + (commands[ii+1] - '0');

      if (DeviceIF::Ok == buoyLauncherIF->currentBuoy(buoynum))
	commandFinished = False;
      break;

    case LC_STATUS:
      ii++;   // Just go to the next command
      break;

    case LCBC_STATUS:
      ii++;   // Just go to the next command
      break;

    case STATUS_ON:
      if (DeviceIF::Ok == buoyLauncherIF->statusOn(True))
	commandFinished = False;
      break;

    case STATUS_OFF:
      if (DeviceIF::Ok == buoyLauncherIF->statusOn(False))
	commandFinished = False;
      break;

    default:
      Syslog::write("Unknown command: %c", thisCmd);
      ii++;   // Just go to the next command
      break;
    }
    now = time((long*)0);
    testTimeout = (now > (start+1200));
  }

  sleep(90);

  delete buoyLauncherIF;

  kill(0, SIGTERM);
  return 0;
}










