// This automatic monitors the status of the input to the VT machine from the video router
// and if camera 1 is switched to this input, it will turn on the red light on the SantaPod.
// This red light can't be turned off manually when the alarm condition is active.
// All driver numbers and inputs/outputs are defined in automatics.xml so no numbers should need 
// to be hard-coded.


#include <windows.h>
#include <stdio.h>
#include <bncs_string.h>
#include <bncs_config.h>
#include "CameraControl.h"
#define PNL_MAIN 1

// this nasty little macro to make our class visible to the outside world
EXPORT_BNCS_SCRIPT( CameraControl )

// constructor - equivalent to ApplCore STARTUP
CameraControl::CameraControl( bncs_client_callback * parent, const char * path ) : bncs_script_helper( parent, path )
{
	m_tx=false;



	// show a panel from file p1.bncs_ui and we'll know it as our panel 1
	panelShow(1, "p1.bncs_ui");
	// get router properties from automatics.xml
	vidRouter = getConfigEntry("automatics.router_values.Bredon_video_router", "value");
	GPIRouter = getConfigEntry("automatics.router_values.Bredon_GPI", "value");
	deviceInfoDriver = getConfigEntry("automatics.router_values.Bredon_info", "value");
	vidDest = getConfigEntry("automatics.monitored_dests", "value");
	cam1 = getConfigEntry("automatics.selected_camera", "value");
	alertGPI = getConfigEntry("automatics.controlled_GPI", "value");

	//register for revertives from video router and GPI device
	routerRegister(vidRouter, vidDest,vidDest);
	routerPoll(vidRouter, vidDest, vidDest);
	gpiRegister(GPIRouter, alertGPI, alertGPI, true);
	gpiPoll(GPIRouter, alertGPI, alertGPI);

	//display name and number of router destination as well as which video driver is being monitored
	routerName(vidRouter, 1, vidDest, vidDestName);
	textPut("text", vidDestName, PNL_MAIN, "VidDestName");
	textPut("text", vidRouter, PNL_MAIN, "VideoRouter");
	textPut("text", vidDest, PNL_MAIN, "VidDestNo");
	textPut("text", m_vidRouter, PNL_MAIN, "VidSrcName");
	// you may need this call to set the size of this component 
	//  if it's used in a popup window 
//	setSize( 1024,668 );		// set the size explicitly
//	setSize( 1 );				// set the size to the same as the specified panel

	// connect to our infodriver host
	m_info = new ccInfodriver( this );

	// don't really hard code yer device number....
	m_info->connect( deviceInfoDriver );
}

// destructor - equivalent to ApplCore CLOSEDOWN
CameraControl::~CameraControl()
{
	delete m_info;
	routerUnregister(vidRouter);
	gpiUnregister(GPIRouter);
}

// all button pushes and notifications come here
void CameraControl::buttonCallback( buttonNotify *b )
{

}

// all revertives come here
int CameraControl::revertiveCallback( revertiveNotify * r )
{
	if (r->device() == vidRouter)	//revertives from video router
	{
		if (r->index() == vidDest)
		{
			textPut("text", r->sInfo(), PNL_MAIN, "VidSrcName");
			textPut("text", r->info(), PNL_MAIN, "VidSrcNo");
			if (r->info() == cam1)
			{
				if (m_tx == true)
					gpiSwitch(GPIRouter, 1, alertGPI, true);
				alertRaised = true;
			}
			else
			{
				if (m_tx == true)
					gpiSwitch(GPIRouter, 0, alertGPI, true);
				alertRaised = false;
			}
		}
	}
	if (r->device() == GPIRouter)	//revertives from GPI driver
	{
		if (r->index() == alertGPI)
		{
			if (r->info() == 1)
			{
				textPut("colour.led", "red", PNL_MAIN, "AlertRaised");
				textPut("text", "ALARM", PNL_MAIN, "AlertRaised");
				textPut("colour.background", "#ffff00", PNL_MAIN, "AlertRaised");
			}
			else if (r->info() == 0)
			{
				//if somebody has turned the light off manually, turn it back on again if we are still in alarm condition
				if (alertRaised == true)
				{
					gpiSwitch(GPIRouter, 1, alertGPI, true);
					textPut("colour.led", "red", PNL_MAIN, "AlertRaised");
					textPut("text", "ALARM", PNL_MAIN, "AlertRaised");
					textPut("colour.text", "red", PNL_MAIN, "AlertRaised");
				}

				else
				{
					textPut("colour.led", "green", PNL_MAIN, "AlertRaised");
					textPut("text", "All OK", PNL_MAIN, "AlertRaised");
					textPut("colour.background", "grey", PNL_MAIN, "AlertRaised");
				}
			}
		}
		
	}
	return 0;
}

// all database name changes come back here
void CameraControl::databaseCallback( revertiveNotify * r )
{
}

// all parent notifications come here i.e. when this script is just one 
//  component of another dialog then our host might want to tell us things
bncs_string CameraControl::parentCallback( parentNotify *p )
{
	if( p->command() == "return" )
	{
		bncs_stringlist sl;
		
		sl << "myParam=" + m_myParam;
		
		return sl.toString( '\n' );
	}
	else if( p->command() == "myParam" )
	{
		m_myParam = p->value();
	}
	return "";
}

// timer events come here
void CameraControl::timerCallback( int id )
{
}



/** Request from client to change a slot
\param[in] device The device number
\param[in] index The slot number
\param[in] slot The requested contents to use
\note This command does not automatically update the contents of the slot
*/
void CameraControl::cciSlotRequest( int device, int index, const string & slot )
{
	// convert incoming STL string to local bncs_string so all our favourite string-wrangling 
	// calls will work (STL string doesn't have many)
	bncs_string s( slot );

	// just use the string s as usual

}

/** Direct message from a client requesting workstation specific information on this device
\param[in] workstation The workstation requesting the information
\param[in] device The device number
\param[in] message The message string from the client
\param[in] reference An arbitary message reference that should be returned with the reply to this command
\sa ccInfodriver::clientMessage();
\note Implementation of this messaging mechanism is patchy so beware....
*/
void CameraControl::cciClientMessage( int workstation, int device, const string & message, const string & clientHandle, const string & reference )
{

}

/** Notification of redundancy state
\param[in] state The current state
*/
void CameraControl::cciRedundancyState( enum cc::redundancyState state )
{
	switch( state )
	{
		case cc::tx:
			// set our internal flag to know whether this automatic is active and we should
			// be sending client commands to the network
			m_tx=true;
			textPut("text", "Active", PNL_MAIN, "Status");
			break;
		case cc::rx:
			m_tx=false;
			textPut("text", "Inactive", PNL_MAIN, "Status");
			break;
	}
}

/** Connected event */
void CameraControl::cciConnected( int )
{
	textPut("text", "Connected to Infodriver", PNL_MAIN, "Status");
}

/** Disconnected event */
void CameraControl::cciDisconnected( int )
{
	textPut("text", "Disconnected from Infodriver", PNL_MAIN, "Status");
}

int CameraControl::getConfigEntry(bncs_string sKey, bncs_string sAttr)
//helper code to query automatics.xml
{
	bncs_string sRet = "";
	int iRet = -1;
	bncs_config c(sKey);
	
	if (c.isValid())
		sRet = c.attr(sAttr);
		iRet = sRet.toInt();
	return iRet;
}