/****************************************************************************/
/* Copyright (c) 2014 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  : behaviour to control edgetech fsdw sidecan/subbotom sonars    */
/* Filename : edgetech.cc                                                   */
/* Author   : Eric Martin                                                   */
/* Project  : Mapper 2 Build & Reson upgrade compatibility                  */
/* Version  : 1.0                                                           */
/* Created  : 0409/2014										 				*/
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/

#include "unix.h"
#include "edgetech.h"
#include "EdgetechFSDWIF.h"
#include "BooleanAttribute.h"
#include "IntegerAttribute.h"
#include "FloatAttribute.h"
#include "StringAttribute.h"
#include "VerticalModeAttribute.h"
#include "MissionTimeAttribute.h"
#include "MathP.h"
#include "Syslog.h"

#define DEFAULT_STRING_ATTR "\"\""
#define NotSpecified -100000.0

edgetech::edgetech()
  : _server(NULL), Behavior(EdgetechBehaviorName, Sequential)
{
  _sbpDone = False;
  _lossDone = False;
  _hissDone = False;
  _logDone = False;
  _storageDone = False;
  _init = False;
  _getUpdates = False;
  Boolean debug = True;

  // Sub-bottom attributes
  attributes.add(new IntegerAttribute("SBP_Mode",
                                      "Sub-bottom profiler on/off (1=On,0=Off)",
				    &_sbpMode, -1));
  attributes.add(new FloatAttribute("SBP_Power", 
                                    "Sub-bottom power level in percent (0.0 or more)",
				    &_sbpPower, -1.));
  attributes.add(new FloatAttribute("SBP_Gain", 
                                    "Sub-bottom receiver gain in power of 2 (up to 2048) (0.0 or more)",
				    &_sbpGain, -1.));
  attributes.add(new FloatAttribute("SBP_Duration", 
                                    "Sub-bottom ping duration in milliseconds (more than 0.0)",
				    &_sbpDuration, -1.));
  attributes.add(new StringAttribute("SBP_PulseFile",
				     "New pulse file name",
				     &_sbpPulseFilename, DEFAULT_STRING_ATTR));
  
  // Low-freq sidescan attributes
  attributes.add(new IntegerAttribute("LoSS_Mode", 
                                      "Low-freq sidescan on/off (1=On,0=Off)",
				    &_lossMode, -1));
  attributes.add(new FloatAttribute("LoSS_Power",
                                    "Low-freq power level in percent (0.0 or more)",
				    &_lossPower, -1.));
  attributes.add(new FloatAttribute("LoSS_Range",
                                    "Low-freq range in meters (0.0 or more)",
				    &_lossRange, -1.));
  attributes.add(new FloatAttribute("LoSS_Rate",
                                    "Low-freq ping rate in PPS (0.0 or more)",
				    &_lossRate, -1.));
  attributes.add(new StringAttribute("LoSS_PulseFile",
				     "New pulse file name",
				     &_lossPulseFilename, DEFAULT_STRING_ATTR));
  
  // High-freq sidescan attributes
  attributes.add(new IntegerAttribute("HiSS_Mode",
                                      "High-freq sidescan on/off (1=On,0=Off)",
				    &_hissMode, -1));
  attributes.add(new FloatAttribute("HiSS_Power",
                                    "High-freq power level in percent (0.0 or more)",
				    &_hissPower, -1.));
  attributes.add(new FloatAttribute("HiSS_Range",
                                    "High-freq range in meters (0.0 or more)",
				    &_hissRange, -1.));
  attributes.add(new FloatAttribute("HiSS_Rate",
                                    "High-freq ping rate in PPS(0.0 or more)",
				    &_hissRate, -1.));
  attributes.add(new StringAttribute("HiSS_PulseFile",
				     "New pulse file name",
				     &_hissPulseFilename, DEFAULT_STRING_ATTR));
  
  // Server functional controls
  attributes.add(new IntegerAttribute("Log_Mode",
                                      "Logging on/off (1=On,0=Off)",
				    &_logMode, -1));

  attributes.add(new IntegerAttribute("Get_Updates",
				      "Request status updates on property changes (1=On, 0=Off)",
		  	  	  	  	  	  	  	  &_getUpdatesMode, 0));

  attributes.add(new IntegerAttribute("Storage_Mode",
				      "Enable Data Storage on Edgetech Systems (1=On, 0=Off)",
		  	  	  	  	  	  	  	  &_storageMode, -1));

  try
  {
     if( !_edgetech) _edgetech = new EdgetechFSDWIF(EdgetechFSDWIFServerName);
  }
  catch (SharedObjectClient::MissingServer e) 
  {
     Syslog::write("edgetech::edgetech() - Missing server: %s; "
		   "continuing.\n",
		   e.msg);
     _edgetech = NULL;
  }

  dprintf("Behavior edgetech: Finished Constructor");
}

edgetech::~edgetech()
{
   if( !_edgetech) 
   {
      delete _edgetech;
      _edgetech = NULL;
   }
}


Boolean edgetech::shouldBehaviorStart( void ) 
{
     return horizontalSequence();
}

void edgetech::execute()
{
  DeviceIF::Status status;
  Boolean debug = True;

  _logDone  = (_logMode < 0);
  _storageDone = (_storageMode < 0);
  _sbpDone  = (_sbpMode < 0 && _sbpPower < 0. && _sbpGain < 0. && _sbpDuration < 0.);
  _hissDone = (_hissMode < 0 && _hissPower < 0. && _hissRate < 0. && _hissRange < 0.);
  _lossDone = (_lossMode < 0 && _lossPower < 0. && _lossRate < 0. && _lossRange < 0.);
  _getUpdates = (_getUpdatesMode == 1);

  Syslog::write("Edgetech Behavior::log=%d,storage=%d, updates=%d | sbp=%d,%f,%s | hiss=%d,%f,%f,%f,%s | loss=%d,%f,%f,%f,%s",
                _logMode,_storageMode,_getUpdatesMode,_sbpMode,_sbpPower, _sbpPulseFilename,
		_hissMode,_hissPower,_hissRate,_hissRange,_hissPulseFilename,
                _lossMode,_lossPower,_lossRate,_lossRange,_lossPulseFilename);

// Interface to Edgetech server opened in LayeredControl
//
  _server = _edgetech;
  
  // Perform the sub-bottom action
  if (!_sbpDone)
  {
    if (_sbpPower >= 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SBP power to %f", _sbpPower);
      status = _server->setPingPower(EdgetechFSDWIF::SubBottom, _sbpPower, _getUpdates);
      if (DeviceIF::Ok == status) _sbpPower = -1.;
    }
    if (_sbpMode == 1)
    {
      Syslog::write("Edgetech Behavior: Starting subbottom profiler");
      status = _server->startSubsystem(EdgetechFSDWIF::SubBottom, _getUpdates);
      if (DeviceIF::Ok == status) _sbpMode = -1;
    }
    else if(_sbpMode == 0)
    {
      Syslog::write("Edgetech Behavior: Stopping subbottom profiler");
      status = _server->stopSubsystem(EdgetechFSDWIF::SubBottom, _getUpdates);
      if (DeviceIF::Ok == status) _sbpMode = -1;
    }
    if (_sbpGain >= 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SBP gain to %f", _sbpGain);
      status = _server->setSBPGain(_sbpGain, _getUpdates);
      if (DeviceIF::Ok == status) _sbpGain = -1.;
    }
    if (_sbpDuration > 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SBP duration to %f", _sbpDuration);
      status = _server->setSBPDuration(_sbpDuration, _getUpdates);
      if (DeviceIF::Ok == status) _sbpDuration = -1.;
    }
    if (strcmp(_sbpPulseFilename,DEFAULT_STRING_ATTR) != 0 ) {
	  Syslog::write("Edgetech Behavior: Setting pulse filename for SBP to %s" , _sbpPulseFilename);
	  status = _server->setPulseFilename(EdgetechFSDWIF::SubBottom, _sbpPulseFilename, _getUpdates);
    }

  }

  // Perform the low freq sidescan action
  if (!_lossDone)
  {
    if (_lossPower >= 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SSLo power to %f",_lossPower);
      status = _server->setPingPower(EdgetechFSDWIF::SideScanLow, _lossPower, _getUpdates);
      if (DeviceIF::Ok == status) _lossPower = -1.;
    }

    if (_lossRange > 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SSLo range to %f",_lossRange);
      status = _server->setPingRange(EdgetechFSDWIF::SideScanLow, _lossRange, _getUpdates);
      if (DeviceIF::Ok == status) _lossRange = -1.;
    }

    if (_lossRate > 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SSLo rate to %f",_lossRate);
      status = _server->setPingRate(EdgetechFSDWIF::SideScanLow, _lossRate, _getUpdates);
      if (DeviceIF::Ok == status) _lossRate = -1.;
    }

    if (_lossMode > 0)
    {
      Syslog::write("Edgetech Behavior: Starting lo-freq SS");
      status = _server->startSubsystem(EdgetechFSDWIF::SideScanLow, _getUpdates);
      if (DeviceIF::Ok == status) _lossMode = -1;

    }
    else if (_lossMode == 0)
    {
      Syslog::write("Edgetech Behavior: Stopping lo-freq SS");
      status = _server->stopSubsystem(EdgetechFSDWIF::SideScanLow, _getUpdates);
      if (DeviceIF::Ok == status) _lossMode = -1;
    }
    if (strcmp(_lossPulseFilename,DEFAULT_STRING_ATTR) != 0 ) {
	  Syslog::write("Edgetech Behavior: Setting pulse filename for LoSS to %s" , _lossPulseFilename);
	  status = _server->setPulseFilename(EdgetechFSDWIF::SideScanLow, _lossPulseFilename, _getUpdates);
    }

  }

  // Perform the high freq sidescan action
  if (!_hissDone)
  {
    if (_hissPower >= 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SSHi power to %f",_hissPower);
      status = _server->setPingPower(EdgetechFSDWIF::SideScanHigh, _hissPower, _getUpdates);
      if (DeviceIF::Ok == status) _hissPower = -1.;
    }

    if (_hissRange > 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SSHi range to %f",_hissRange);
      status = _server->setPingRange(EdgetechFSDWIF::SideScanHigh, _hissRange, _getUpdates);
      if (DeviceIF::Ok == status) _hissRange = -1.;
    }

    if (_hissRate > 0.)
    {
      Syslog::write("Edgetech Behavior: Setting SSHi rate to %f",_hissRate);
      status = _server->setPingRate(EdgetechFSDWIF::SideScanHigh, _hissRate, _getUpdates);
      if (DeviceIF::Ok == status) _hissRate = -1.;
    }

    if (_hissMode > 0)
    {
      Syslog::write("Edgetech Behavior: Starting hi-freq SS");
      status = _server->startSubsystem(EdgetechFSDWIF::SideScanHigh, _getUpdates);
      if (DeviceIF::Ok == status) _hissMode = -1;
    }
    else if (_hissMode == 0)
    {
      Syslog::write("Edgetech Behavior: Stopping hi-freq SS");
      status = _server->stopSubsystem(EdgetechFSDWIF::SideScanHigh, _getUpdates);
      if (DeviceIF::Ok == status) _hissMode = -1;
    }
    if (strcmp(_hissPulseFilename,DEFAULT_STRING_ATTR) != 0 ) {
	  Syslog::write("Edgetech Behavior: Setting pulse filename for SBP to %s" , _hissPulseFilename);
	  status = _server->setPulseFilename(EdgetechFSDWIF::SideScanHigh, _hissPulseFilename, _getUpdates);
    }

  }


  // Perform the data logging action
  if (!_storageDone)
  {
	  unsigned char errorCnt = 0;
	  if (_storageMode & 0x01)
	  {
		  Syslog::write("Edgetech Behavior: Starting Edgetech Data Storage");
		  status = _server->startEdgetechStorage(_getUpdates);
		  if (DeviceIF::Ok != status) errorCnt++;
	  }
	  else
	  {
		  Syslog::write("Edgetech Behavior: Stopping Edgetech Data Storage");
		  status = _server->stopEdgetechStorage(_getUpdates);
		  if (DeviceIF::Ok != status) errorCnt++;
	  }
	  if (errorCnt == 0) {
		  _storageMode = -1;
		  _storageDone = True;
	  }
  }

  // Perform the logging action
  if (!_logDone)
  {
    unsigned char errorCnt = 0;
    if (_logMode  & 0x01)
    {
      Syslog::write("Edgetech Behavior: Starting logging");
      status = _server->dataLoggingOn();
      if (DeviceIF::Ok != status) errorCnt++;
    }
    else
    {
      Syslog::write("Edgetech Behavior: Stopping logging");
      status = _server->dataLoggingOff();
      if (DeviceIF::Ok != status) errorCnt++;
    }
    /*
    if (_logMode & 0x02)
    {
      Syslog::write("Edgetech Behavior: Starting 7k Center Logging");
      status = _server->start7KCenterLogging();
      if (DeviceIF::Ok != status) errorCnt++;
    }
    else
    {
      Syslog::write("Edgetech Behavior: Stopping 7k Center Logging");
      status = _server->stop7KCenterLogging();
      if (DeviceIF::Ok != status) errorCnt++;
    }
    */
    if (errorCnt == 0) {
	_logMode = -1;
	_logDone = True;
    }

  }


 
  // Finished if all actions performed successfully
  if (_sbpDone && _logDone && _lossDone && _hissDone )
    setState(Finished);

  return;
}


Boolean edgetech::validInput()
{
  Boolean valid = True;

  return valid;
}

