/****************************************************************************/
/* Copyright (c) 2015 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : CARL.cc                                                       */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/10/2015                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/

#include "CARL.h"
#include "BooleanAttribute.h"
#include "IntegerAttribute.h"
#include "FloatAttribute.h"
#include "StringAttribute.h"
#include "MathP.h"
#include "Syslog.h"
#include "System.h"
#include "TimeP.h"

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

CARL::CARL()
  : Behavior(CARLBehaviorName, Sequential), _server(NULL),
  _inLightSwitch(False), _inRecorderSwitch(False),
  _inRecord(False), _inBrightness(False), _inHomeIris(False),
  _inFstop(False), _timer(-1)
{
  _init = False;

  Boolean debug = False;

  //  Recorder switch 
  attributes.add(new IntegerAttribute("recorderSwitch",
      "Recorder switch (1=On,0=Off)",
              &_recorderSwitch, -1));

  //  Camera switch 
  attributes.add(new IntegerAttribute("cameraSwitch",
      "Camera switch (1=On,0=Off)",
              &_cameraSwitch, -1));
  
  //  CTD switch 
  attributes.add(new IntegerAttribute("ctdSwitch",
                                      "CTD switch (1=On,0=Off)",
              &_ctdSwitch, -1));
  //  Light switch 
  attributes.add(new IntegerAttribute("lightSwitch",
      "Light switch (1=On,0=Off)",
              &_lightSwitch, -1));
  //  Light intensity  
  attributes.add(new IntegerAttribute("brightness",
                                      " (0=Lowest,100=Highest)",
				      &_brightness, -1));

  //  Record start/stop 
  attributes.add(new IntegerAttribute("record",
                                      "Record Button (1=Action!,0=Cut!)",
              &_record, -1));

  //  Home position  
  attributes.add(new IntegerAttribute("homeIris",
                                      "Home the iris motor (1=Home)",
              &_homeIris, -1));

  //  FStop position  
  attributes.add(new IntegerAttribute("fstop",
                                      "Coded FStop position: Valid values are "
                                      "31,32,33,41,42,43,561,562,563,81,82,83"
                                      "111,112,113,161,162,163,221",
              &_fstop, -1));
  //  Reset clipname to current date/time 
  attributes.add(new IntegerAttribute("clipname",
      "Reset clipname to current date and time (1=On,0=Off)",
              &_clipname, -1));

   if (!Behavior::_carl)
   {
     try {
        Behavior::_carl = new CARL_IF("CARLServer");
     }
     catch (Exception e) {
       Syslog::write("CARL Behavior - %s", e.msg);
       Behavior::_carl = NULL;
     }
     catch (...) {
       Syslog::write("CARL Behavior - Exception while connecting to CARLServer");
       Behavior::_carl = NULL;
     }
   }
   _server = Behavior::_carl;

}

CARL::~CARL()
{
   if( !_server) 
   {
      delete _server;
      _server = NULL;
   }
}

Boolean CARL::shouldBehaviorStart( void ) 
{
  return bothSequence();
}

void CARL::execute()
{
  DeviceIF::Status status;
  Boolean debug = False;

  dprintf("CARL - Id:%d, Duration:%f, cameraSwitch:%d, recorderSwitch:%d, "
              "lightSwitch:%d, brightness:%d, record:%d, homeIris:%d, fstop:%d\n",
              _id, _duration, _cameraSwitch, _recorderSwitch, _lightSwitch,
              _brightness, _record, _homeIris, _fstop);

  // Set the time at which the behavior should be finished
  //
  if (_timer <= 0)
  {
    // Must be the first call to execute
    _timer = Time::milliseconds() + (_duration*1000);
    Syslog::write("CARL - Duration:%f, cameraSwitch:%d, recorderSwitch:%d, "
              "lightSwitch:%d, brightness:%d, record:%d, homeIris:%d, fstop:%d",
              _duration, _cameraSwitch, _recorderSwitch, _lightSwitch,
              _brightness, _record, _homeIris, _fstop);

  }

  if (Time::milliseconds() > _timer)
  {
    Syslog::write("CARL::execute() - CARL id %d timeout! (%ld > %ld) ", _id,
      Time::milliseconds(), _timer);
    //setState(Finished);     // Nothing more to do
    //return;
  }

  if (_server == NULL)
  {
    Syslog::write("CARL::execute() - Sorry, not connected to server");
    return;
  }

  if (_recorderSwitch < 0 &&
      _cameraSwitch < 0   &&
      _ctdSwitch < 0      &&
      _lightSwitch < 0    &&
      _brightness < 0     &&
      _fstop < 0          &&
      _homeIris < 0       &&
      _clipname < 0       &&
      _record < 0 )
  {
    Syslog::write("CARL::execute() - %d all done!", _id);
    setState(Finished);     // Nothing more to do
    return;
  }

  // Perform the actions listed in the behavior once
  //
  // camera switch
  //
  if (_cameraSwitch != -1)
  {
    // Request the switch to be set or reset
    //
    if (_cameraSwitch > 0)
    {
      Syslog::write("CARL Behavior %d: Turning camera on", _id);
      _server->camera_bus_on();
    }
    else if (_cameraSwitch == 0)
    {
      Syslog::write("CARL Behavior %d: Turning camera off", _id);
      _server->camera_bus_off();
    }
    _cameraSwitch = -1;
    return;
  }


  // Recorder switch
  //
  if (_recorderSwitch != -1)
  {
    // Perform the action if this is the first time through
    //
    if (!_inRecorderSwitch)
    {
      _inRecorderSwitch = True;
      if (_recorderSwitch > 0)
      {
        Syslog::write("CARL Behavior %d: Turning recorder on", _id);
        _server->recorder_on();
      }
      else if (_recorderSwitch == 0)
      {
        Syslog::write("CARL Behavior %d: Turning recorder off", _id);
        _server->recorder_off();
      }
    }
    else
    {
      _recorderSwitch = -1;
      _inRecorderSwitch = False;
    }
    return;
  }

  // Light brightness (should be before light switch)
  //
  if (_brightness != -1) {
    if (!_inBrightness)
    {
      _inBrightness = True;

      if (_brightness > 80) _brightness = 80;
      Syslog::write("CARL Behavior %d: Setting brightness to %d",
        _id, _brightness);
      _server->light_level(_brightness);
    }
    else
    {
      _brightness = -1;
      _inBrightness = False;
    }
    return;
  }

  // Reset clipname
  //
  if (_clipname != -1) {
    Syslog::write("CARL Behavior %d: Setting clipname", _id);
    _server->set_clipname("");
    _clipname = -1;
    return;
  }

  // Light switch
  //
  if (_lightSwitch != -1)
  {
    // Perform the action if this is the first time through
    //
    if (!_inLightSwitch)
    {
      _inLightSwitch = True;
      if (_lightSwitch > 0)
      {
        _lightSwitch = 1;
        Syslog::write("CARL Behavior %d: Turning lights on", _id);
        _server->camera_lights_on();
      }
      else if (_lightSwitch == 0)
      {
        Syslog::write("CARL Behavior %d: Turning lights off", _id);
        _server->camera_lights_off();
      }
    }
    else
    {
      _lightSwitch = -1;         // Done with light switch
      _inLightSwitch = False;
    }
    return;
  }

  // Record button
  //
  if (_record != -1)
  {
    if (_record > 0)
    {
      Syslog::write("CARL Behavior %d: action!", _id);
      _server->start_recording();
      _record = -1;      // Reset after usage
    }
    else if (_record == 0)
    {
      Syslog::write("CARL Behavior %d: cut!", _id);
      _server->stop_recording();
      _record = -1;      // Reset after usage
    }
    _record = -1;      // Reset after usage
    Syslog::write("CARL Behavior %d: resetting record", _id);
    return;
  }

  // Home
  //
  if (_homeIris > 0)
  {
    Syslog::write("CARL Behavior %d: Home the iris motor", _id);
    _server->iris_control(CARL_IF::Home, 0);
    _homeIris = -1;      // Reset after usage
    return;
  }

  // FStop
  //
  if (_fstop > -1)
  {
    Syslog::write("CARL Behavior %d: set the fstop to %d", _id, _fstop);
    _server->iris_control(CARL_IF::FStop, _fstop);
    _fstop = -1;      // Reset after usage
    return;
  }

  return;
}


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

  if (_recorderSwitch < -1 || _recorderSwitch > 1)
  {
    Syslog::write("CARL Behavior %d: invalid value for recorderSwitch: %d",
      _id, _recorderSwitch);
    valid = False;
  }

  if (_ctdSwitch < -1 || _ctdSwitch > 1)
  {
    Syslog::write("CARL Behavior %d: invalid value for ctdSwitch: %d",
      _id, _ctdSwitch);
    valid = False;
  }

  if (_lightSwitch < -1 || _lightSwitch > 1)
  {
    Syslog::write("CARL Behavior %d: invalid value for lightSwitch: %d", 
      _id, _lightSwitch);
    valid = False;
  }

  if (_brightness < -1 || _brightness > 100)
  {
    Syslog::write("CARL Behavior %d: invalid value for brighness: %d",
      _id, _brightness);
    valid = False;
  }

  if (_fstop >= 0)
  {
    if ( (_fstop < 31) ||
         (_fstop > 33 && _fstop < 41) ||
         (_fstop > 43 && _fstop < 81) ||
         (_fstop > 83 && _fstop < 111) ||
         (_fstop > 113 && _fstop < 161) ||
         (_fstop > 163 && _fstop < 221) ||
         (_fstop > 221 && _fstop < 561) ||
         (_fstop > 563)
       )
    {
       Syslog::write("CARL Behavior %d: invalid value for fstop: %d",
        _id, _fstop);
       valid = False;
    }
  }

  return valid;
}

