/****************************************************************************/
/* Copyright (c) 2012 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : DeltaTServer.cc                                          */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 09/17/2012                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#include <process.h>

#include <time.h>
#include "Syslog.h"
#include "DeltaTIF_SK.h"
#include "DeltaTServer.h"
#include "FloatAttribute.h"
#include "AngleAttribute.h"

DeltaTServer::DeltaTServer(const char *configFileName) 
    : _attributes("DeltaTServer")
{
  _input = new DeltaTInput(SharedData::ReadWrite);
  _output = new DeltaTOutput(SharedData::ReadWrite);

  _msgQ = new DeltaTMessage(MessageQueue::Write, DeltaTMessageQueueName);

  //AttributeParser::parse(configFileName, &_attributes);
}


DeltaTServer::~DeltaTServer()
{
  delete _input;
  delete _output;
}

DeviceIF::Status DeltaTServer::set_gain(short gain)
{
  if (gain < 1 || gain > 20) {
    Syslog::write("DeltaTServer: Gain value of %d is invalid (should be 1 to 20)", gain);
    return DeviceIF::Error;
  }

  long lgain = gain;
  DeltaTMessage::Message set_gain(DeltaTMessage::SetGain, lgain);
  _msgQ->write(&set_gain);

  return DeviceIF::Ok;
}

DeviceIF::Status DeltaTServer::set_averaging(short avg)
{
  if (avg == 0 || avg == 1  //Averaging, 0,1=Off, 3, 5, 7 = #shots to average
      || avg == 3 || avg == 5 || avg == 7) {
    long lavg = avg;
    DeltaTMessage::Message set_avg(DeltaTMessage::SetAveraging, lavg);
    _msgQ->write(&set_avg);
    return DeviceIF::Ok;
  }
  else {
    Syslog::write("DeltaTServer: Averaging value of %d is invalid (0|1|3|5|7)", avg);
    return DeviceIF::Error;
  }
}

DeviceIF::Status DeltaTServer::set_beam_width(short width)
{
  //Beamwidth, 0=Wide, 1=Normal, 2=Narrow, 3=Narrow Mixed
  if (width >= 0 && width <=3) {
    long lwidth = width;
    DeltaTMessage::Message set_width(DeltaTMessage::SetBeamWidth, lwidth);
    _msgQ->write(&set_width);
    return DeviceIF::Ok;
  }
  else {
    Syslog::write("DeltaTServer: Beam width value of %d is invalid (0|1|2|3)", width);
    return DeviceIF::Error;
  }
}

DeviceIF::Status DeltaTServer::set_sector_size(short size)
{
  if (size == 30 || size == 60 || size == 90 || size == 120) {
    long lsize = size;
    DeltaTMessage::Message set_size(DeltaTMessage::SetSectorSize, lsize);
    _msgQ->write(&set_size);
    return DeviceIF::Ok;
  }
  else {
    Syslog::write("DeltaTServer: Invalid sector size value: %d (30|60|90|120)", size);
    return DeviceIF::Error;
  }
}

DeviceIF::Status DeltaTServer::set_nbeams(short nb)
{
  if (nb == 120 || nb == 240 || nb == 480) {
    long lnb = nb;
    DeltaTMessage::Message set_nbeams(DeltaTMessage::SetNBeams, lnb);
    _msgQ->write(&set_nbeams);
    return DeviceIF::Ok;
  }
  else {
    Syslog::write("DeltaTServer: Invalid value for nbeams: %d (120|240|480)", nb);
    return DeviceIF::Error;
  }
}

DeviceIF::Status DeltaTServer::set_gain_eq(Boolean on)
{
  long on_off;
  if (on)
    on_off = 1;
  else
    on_off = 0;

  DeltaTMessage::Message set_gain_eq(DeltaTMessage::SetGainEq, on_off);
  _msgQ->write(&set_gain_eq);

  return DeviceIF::Ok;
}

DeviceIF::Status DeltaTServer::set_sos(short sos)
{
  long lsos = sos;
  DeltaTMessage::Message set_sos(DeltaTMessage::SetSOS, lsos);
  _msgQ->write(&set_sos);

  return DeviceIF::Ok;
}

DeviceIF::Status DeltaTServer::set_range(short range)
{
  long lrange = range;
  DeltaTMessage::Message set_range(DeltaTMessage::SetRange, lrange);
  _msgQ->write(&set_range);

  return DeviceIF::Ok;
}

void DeltaTServer::start()
{
  _input->data.enabled = True;
  _input->write();

  DeltaTMessage::Message start_log(DeltaTMessage::StartMVCLogging);
  _msgQ->write(&start_log);
}

void DeltaTServer::stop()
{
  _input->data.enabled = False;
  _input->write();

  DeltaTMessage::Message stop_log(DeltaTMessage::StopMVCLogging);
  _msgQ->write(&stop_log);
}

Boolean DeltaTServer::enabled()
{
  _output->read();
  return _output->data.enabled;
}

void DeltaTServer::name(DeviceIF::Name name)
{
  strcpy(name, "DeltaTServer");
}

double DeltaTServer::range()
{
  _output->read();
  return _output->data.dt_range;
}

unsigned short DeltaTServer::nbeams()
{
  _output->read();
  return _output->data.nbeams;
}

unsigned short DeltaTServer::interval()
{
  _output->read();
  return _output->data.dt_interval;
}

void DeltaTServer::update_time(TimeIF::TimeSpec *updateTime)
{
  _output->read();
  updateTime->seconds      = _output->data.update_time.seconds;
  updateTime->nanoSeconds  = _output->data.update_time.nanoSeconds;

  return;
}

void DeltaTServer::get(DeltaTIF::Data *data)
{
  _output->read();
  _input->read();
  data->enabled = _input->data.enabled;
  data->update_time.seconds      = _output->data.update_time.seconds;
  data->update_time.nanoSeconds  = _output->data.update_time.nanoSeconds;
  data->range = _output->data.dt_range;
  data->interval = _output->data.dt_interval;
  data->nbeams = _output->data.nbeams;

  for (int i = 0; i < data->nbeams; i++) {
    data->beam_ranges[i] = _output->data.beam_ranges[i];
    data->intensities[i] = (short)_output->data.intensities[i];
  }

}

int DeltaTServer::spawnAuxTasks()
{
  char *program = "delta_t";

  char errorBuf[256];
  char buf[256];
 
  pid_t pid;
 
  switch ((pid = fork())) {
     
  case 0:
    // In child
    // Execute driver program
    execlp(program, program, (char *)0);

    sprintf(errorBuf, 
	    "Task::spawnServer() - exec() of \"%s\" failed", program);

    perror(errorBuf);
 
    break;

  case -1:
    perror("Task::spawnServer() - fork() failed");
    return -1;
  }

  return 0;
}
