/*

*/

#include <windows.h>
#include <stdio.h>
#include <bncs_string.h>
#include <bncs_config.h>
#include "VideoDest.h"

#define MAIN_PANEL	1
#define PANEL_NAME	"mymon.bncs_ui"

#define TIMER_CLRMSG	1
#define TIMER_CLRMSG_PERIOD 250

#define BNCS_DRV_MIN 1
#define BNCS_DRV_MAX 999
#define BNCS_DEST_MIN 1

// Make our class visible to the outside world
EXPORT_BNCS_SCRIPT(VideoDest)


/////////////////////////////////////////////////
// Cconstructor - equivalent to ApplCore STARTUP.
VideoDest::VideoDest( bncs_client_callback * parent, const char * path ) : bncs_script_helper( parent, path )
{
	// Initialise our control variables
	m_instance = "";		// Defines our controlled matrix and crosspoint
	m_selectedbg = "";		// The state used to highlight behine monitor icon showing this control is active
	m_deselectedbg = "";	// The state that shows this control is not active

	m_matrixID = 0;				// BNCS Matrix driver ID, extracted from instance data.
	m_dest = -1;					// Destination switched by this component.
	m_selected = false;			// When active, this component is active.

	// Show our panel
	panelShow(MAIN_PANEL, PANEL_NAME);
}


/////////////////////////////////////////////////
// Destructor - equivalent to ApplCore CLOSEDOWN.
VideoDest::~VideoDest()
{
}


/////////////////////////////////////////////////
// All button pushes and notifications come here.
void VideoDest::buttonCallback(buttonNotify *b)
{
	if ((b->panel() == MAIN_PANEL) && (b->id() == "Monitor"))
	{
		// Only one button on our panel, we are making ourself active
		hostNotify(bncs_string("activate=%1").arg(m_dest));
	}
}


////////////////////////////
// All revertives come here.
int VideoDest::revertiveCallback(revertiveNotify *r)
{
	// We do not register for any revertive data
	return 0;
}


////////////////////////////////////////////
// All database name changes come back here.
void VideoDest::databaseCallback(revertiveNotify *r)
{
	// We have no interest in name changes
}


///////////////////////////////////////////////////////////////
// All parent notifications come here. Most of our information
// comes through this software interface.
bncs_string VideoDest::parentCallback(parentNotify *p)
{
	if (p->command() == "return")
	{
		if (p->value() == "all")
		{	
			// Persisting values for bncs_vis_ed
			bncs_stringlist sl;

			sl << bncs_string("selectedbg=%1").arg(m_selectedbg);
			sl << bncs_string("deselectedbg=%1").arg(m_deselectedbg);

			return sl.toString( '\n' );
		}
	}


	else if (p->command() == "source")
	{
		int new_source = 0;

		// We have received a new source route request. Only relevant if this control is active.
		if (m_selected)
		{
			if (p->value() != "") 
			{
				if ((m_matrixID >= BNCS_DRV_MIN) && (m_matrixID <= BNCS_DRV_MAX) && (m_dest >= BNCS_DEST_MIN))
				{
					new_source = p->value().toInt();							// Extract the source number
					if (new_source >= 0)
					{
						routerCrosspoint(m_matrixID, new_source, m_dest, "", true);	// Make the route
						timerStart(TIMER_CLRMSG, TIMER_CLRMSG_PERIOD);				// Initiate source clear message
					}
				}
			}
		}
		// Extract the matrix and destination. Store in our control variables
	}


	else if (p->command() == "activedest")
	{
		// A control has sent the new active destination value
		if (m_dest == p->value().toInt())
		{
			// The received destination is ours - so make this control active
			m_selected = true;
			textPut("statesheet", m_selectedbg, MAIN_PANEL, "Ident");
		}
		else
		{
			m_selected = false;
			textPut("statesheet", m_deselectedbg, MAIN_PANEL, "Ident");
		}
	}

	else if (p->command() == "instance" && p->value() != m_instance)
	{
		// Our instance is being set/changed
		m_instance = p->value();

		if (p->value() != "")
		{
			// Extract the matrix and destination. Store in our control variables
			if (!getDev(p->value(), &m_matrixID, &m_dest))
			{
				// Instance lookup failed - so be defensive
				m_matrixID = 0;
				m_dest = 0;
			}
		}
		else
		{
			// Instance string is blank
			m_matrixID = 0;
			m_dest = 0;
		}
	}


	else if( p->command() == "selectedbg" )
	{	
		// The colour shown behind the monitor Icon when this component is selected
		m_selectedbg = p->value();

		if (m_selected)
		{
			// This instance is selected, so update the background.
			textPut("statesheet", m_selected, MAIN_PANEL, "Ident");
		}
	}


	else if (p->command() == "deselectedbg")
	{
		// The colour shown behind the monitor Icon when this component is deselected
		m_deselectedbg = p->value();

		if (!m_selected)
		{
			// This instance is not selected, so update the background.
			textPut("statesheet", m_deselectedbg, MAIN_PANEL, "Ident");
		}
	}


	// ***** CONNECTIONS EVENTS HELPER LIST *****
	else if( p->command() == "_events" )
	{	
		// Helper-list of everything in this component generated by hostNotify's
		bncs_stringlist sl;

		sl << "activate=*";		// The message to the connections engine that will send "activedest" to all instances
		sl << "clearsource=-1";	// Sent to indicate we have sent a crosspoint request. Pass to the source selector to clear it

		return sl.toString( '\n' );
	}


	// ***** CONNECTIONS COMMANDS HELPER LIST *****
	else if( p->command() == "_commands" )
	{	
		// Helper-list of any commands/parameters you might want to set at run-time
		bncs_stringlist sl;
		
		sl << "source=[value]";
		sl << "activedest=[value]";
		
		return sl.toString( '\n' );
	}

	return "";
}

//////////////////////////
// Timer events come here.
void VideoDest::timerCallback( int id )
{
	switch (id)
	{
		case TIMER_CLRMSG:
			// Send a clear source message to the host
			hostNotify("clearsource=-1");
			timerStop(TIMER_CLRMSG);
			break;

		default:	// Unhandled timer event
			timerStop(id);
			break;
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// Callbacks above - Methods below ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////


