#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <mbariTypes.h>
#include "lapBox.h"
#include "LapBoxMicro.h"

#define dprintf if (debug) fprintf


LapBoxMicro::LapBoxMicro(const char *name, Nat16 serialChanNo)
  : MicroInterface(name, serialChanNo)
{
  MBool debug = TRUE;

#ifdef UNIX

  /* Create Update semaphores              */
  dprintf(stderr, "LapBoxMicro constructor; semBCreate()...");
  if ((_dmUpdateSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == SEM_NULL)
  {
    fprintf(stderr, "LapBoxMicro::LapBoxMicro() - semBCreate failed\n");
    exit(1);
  }
  
  dprintf(stderr, "done.\n");
    
  _data = new LapBoxUiData(name, DmConsumeFlag);
  _events = new LapBoxUiEvents(name, DmConsumeFlag, _dmUpdateSem);
  _settings = new LapBoxUiSettings(name, DmProvideFlag);

  _dmGroup = dm_create_group();  /* Create Data Manager Group for items */

  dm_group_add_item(_dmGroup, _events->portLight->getHandle(),  
		    &_portLightBit);

  dm_group_add_item(_dmGroup, _events->portCamera->getHandle(), 
		    &_portCameraBit);

  dm_group_add_item(_dmGroup, _events->stbdLight->getHandle(),  
		    &_stbdLightBit);

  dm_group_add_item(_dmGroup, _events->stbdCamera->getHandle(), 
		    &_stbdCameraBit);

  dm_group_add_item(_dmGroup, _events->panoramic->getHandle(),  
		    &_panoramicBit);

  dm_group_add_item(_dmGroup, _events->enable->getHandle(),     
		    &_enableBit);    

  dm_group_add_item(_dmGroup, _events->portCameraSelect->getHandle(),
		    &_portCameraSelectBit);

  dm_group_add_item(_dmGroup, _events->stbdCameraSelect->getHandle(), 
		    &_stbdCameraSelectBit);

  dm_group_add_item(_dmGroup, _events->autoIris->getHandle(), &_autoIrisBit);

#else
#endif
}



/* UNIX version */
LapBoxMicro::~LapBoxMicro()
{
  fprintf(stderr, "In LapBoxMicro Destructor..\n");
#ifdef UNIX
  semDelete(_dmUpdateSem);
#endif
}

/* UNIX version */
int LapBoxMicro::readData(Int16 *joystickX,
			  Int16 *joystickY,
			  Int16 *zoom,
			  Int16 *focus,
			  Int16 *iris)

{

#ifdef UNIX   
    DM_Time dmTime;

    _data->pan->read(joystickX,  &dmTime);
    _data->tilt->read(joystickY, &dmTime);
    _data->zoom->read(zoom,      &dmTime);
    _data->focus->read(focus,    &dmTime);
    _data->iris->read(iris,      &dmTime);
#else
    Int16 cmdStatus;
    Word reply[6];

    if (sendCmd(&reply, sizeof(Word) * 6, 
                          1, LAP_BOX_APP | GET_AXIS)==ERROR)
     
    if (getWord(reply, 0)!= CMD_OK)
      return(ERROR);

    getWords(reply, 6, &cmdStatus, joystickX, joystickY,
                          zoom, focus, iris);

#endif

    //Return Status
    return (OK);
};//readData


/* UNIX version */
int LapBoxMicro::writeSettings(LapBoxButton button, LapBoxButtonState state, 
                               MBool flash)
{
#ifdef UNIX
   DmNat16Object *obj;
   DM_Time dmTime;

   switch (button)
   {
     case ENABLE_BUTTON:
        obj = _settings->enable;
	break;

     case PORT_LIGHT_BUTTON:
	obj = _settings->portLight;
	break;

     case PORT_CAMERA_BUTTON:
	obj = _settings->portCamera;
	break;

     case STBD_LIGHT_BUTTON:
	obj = _settings->stbdLight;
	break;

     case STBD_CAMERA_BUTTON:
	obj = _settings->stbdCamera;
	break;

     case PANORAMIC_BUTTON:
	obj = _settings->panoramic;
	break;

     case PORT_CAMERA_SELECT_BUTTON:
	obj = _settings->portCameraSelect;
	break;

     case STBD_CAMERA_SELECT_BUTTON:
	obj = _settings->stbdCameraSelect;
	break;

     case AUTO_IRIS_BUTTON:
	obj = _settings->autoIris;
	break;

     default:
	return 0;

   }//end case

   Nat16 value = LapBoxUiSettings::encode(state, flash);

   dmTime.tv_sec = time(NULL);
   dmTime.tv_usec = 0;
   
   obj->write(value, &dmTime);
#else
   
   Word cmdStatus[2];
   
   switch (button)
   {
     case ENABLE_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | ENABLED_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case PORT_LIGHT_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | PORT_LIGHT_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case PORT_CAMERA_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | PORT_CAMERA_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case STBD_LIGHT_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | STBD_LIGHT_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case STBD_CAMERA_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | STBD_CAMERA_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case PANORAMIC_BUTTON:
	sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | PANORAMIC_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
        break;

     case PORT_CAMERA_SELECT_BUTTON:
	sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | PORT_CAM_SEL_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
        break;

     case STBD_CAMERA_SELECT_BUTTON:
	sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | STBD_CAM_SEL_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case AUTO_IRIS_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | AUTO_IRIS_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case FOCUS_CAPTURE:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | FOCUS_CAP_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case SENSITIVITY_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | SPARE1_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;

     case MEMORY_BUTTON:
        sendCmd(&cmdStatus, sizeof(cmdStatus), 
                2, LAP_BOX_APP | SPARE2_LAMP_CONTROL, state);
        return(getWord(cmdStatus, 0) == CMD_OK ? OK : ERROR);        
	break;
     
     default:
	break;

   }//end case
#endif
   return(0);
}


/* UNIX version */
MBool LapBoxMicro::readEvent(LapBoxButton *button)
{
  *button = NO_BUTTON;
#ifndef UNIX
  Word srqRequest;
  Byte buffer[SRQ_PACKET_LEN];
#endif

#ifdef UNIX
  /* Wait for any data items to change     */
  semTake(_dmUpdateSem, WAIT_FOREVER);

  DWord groupItem = dm_get_group_changes(_dmGroup);
  if (groupItem == 0)
    return FALSE;
  
    if(groupItem & _portLightBit)
    {
          *button = PORT_LIGHT_BUTTON;
    }
    if(groupItem & _portCameraBit)
    {
          *button = PORT_CAMERA_BUTTON;
    }
    if(groupItem & _stbdLightBit)
    {
          *button = STBD_LIGHT_BUTTON;
    }
    if(groupItem & _stbdCameraBit)
    {
          *button = STBD_CAMERA_BUTTON;
    }
    if(groupItem & _panoramicBit)
    {
          *button = PANORAMIC_BUTTON;
    }
    if(groupItem & _enableBit)
    {
          *button = ENABLE_BUTTON;
    }
    if(groupItem & _portCameraSelectBit)
    {
          *button = PORT_CAMERA_SELECT_BUTTON;
    }
    if(groupItem & _stbdCameraSelectBit)
    {
          *button = STBD_CAMERA_SELECT_BUTTON;
    }
    if(groupItem & _autoIrisBit)
    {
          *button = AUTO_IRIS_BUTTON;
    }
#else
    if(readSRQ(buffer, SRQ_PACKET_LEN, WAIT_FOREVER)!= ERROR)
       
    srqRequest = getWord(&buffer, 0);

    switch(srqRequest)
    {
      case MICRO_RESET_SRQ:
        return(TRUE);
        //if (microIOCtrl->announcesResets)
        //    microResetEventDm(dmItems->microDm.resetEvent);
        break;
      case PORT_LIGHT_SRQ:
        *button = PORT_LIGHT_BUTTON;
        break;

      case PORT_CAMERA_SRQ:
        *button = PORT_CAMERA_BUTTON;
        break;
    
      case STBD_LIGHT_SRQ:
        *button = STBD_LIGHT_BUTTON;
        break;

      case STBD_CAMERA_SRQ:
        *button = STBD_CAMERA_BUTTON;
        break;
      
      case PANO_SRQ:
        *button = PANORAMIC_BUTTON;
        break;

      case LAP_BOX_ENABLE_SRQ:    
        *button = ENABLE_BUTTON;
        break;

      case PORT_CAMERA_SELECT_SRQ:
        *button = PORT_CAMERA_SELECT_BUTTON;
        break;

      case STBD_CAMERA_SELECT_SRQ:
        *button = STBD_CAMERA_SELECT_BUTTON;
        break;

      case AUTO_IRIS_SRQ:
        *button = AUTO_IRIS_BUTTON;
        break;
      
      case SPARE1_SRQ:
        *button = SENSITIVITY_BUTTON;
        break;

      case SPARE2_SRQ:
        *button = MEMORY_BUTTON;
        break;
      
      default:
        printf("LapBox: Unrecognized SRQ 0x%x\n", srqRequest);
    }
#endif
    return FALSE;  

}//readEvent




















