#include <windows.h>
#include <stdio.h>
#include <bncs_string.h>
#include <bncs_config.h>
#include "LocalAudio.h"

#define PNL_MAIN	1
#define CAR_AUDIO_NAME "CAR Audio Router"

#define TIMER_TAKE	1

// ++++++++++++++++++++++++++++++++++++++++++++ //
// Make our class visible to the outside world. //
// ++++++++++++++++++++++++++++++++++++++++++++ //
EXPORT_BNCS_SCRIPT( LocalAudio )

// +++++++++++++++++++++++++++++++++++++++++++++ //
// Constructor - equivalent to ApplCore STARTUP. //
// +++++++++++++++++++++++++++++++++++++++++++++ //
LocalAudio::LocalAudio( bncs_client_callback * parent, const char * path ) : bncs_script_helper( parent, path )
{
	// Ensure sensible defaults are set for the variables
	source_selected = false;
	dest_selected = false;
	source_index = 0;
	dest_index = 0;
	myLocalAudio = 0;
	car_router = 0;

	panelShow( PNL_MAIN, "p1.bncs_ui" );

	// Extract the classroom= parameter from the workstation file
	ws_sl = getWorkstationSetting("classroom").upper();

	// Read the various data from the global parameters file
	myVals = bncs_config("wn_academy." + ws_sl + ".audiorouter");			// Local Analogue Audio Router
	myLocalAudio = myVals.attr("value").toInt();

	myVals = bncs_config("wn_academy." + ws_sl + ".car_audio_os_first");	// First OS destination
	myFirstOS = myVals.attr("value").toInt();

	myVals = bncs_config("wn_academy." + ws_sl + ".car_audio_os_last");	// Last OS destination
	myLastOS = myVals.attr("value").toInt();

	getDev(CAR_AUDIO_NAME, &car_router);

	// Set up the router parameters in the panel
	textPut("device", myLocalAudio, 1, 1);		// Identify the source device ID for control 1
	textPut("device.map", myLocalAudio, 1, 1);	// Identify the source map device. Database is set in p1_bncs.ui
	textPut("device", myLocalAudio, 1, 2);		// Identify destination device ID for control 2	

	// Register for revertives from CAR SD router
	routerRegister(car_router, myFirstOS, myLastOS);

	// Now poll our destinations
	routerPoll(car_router, myFirstOS, myLastOS);

}


// ++++++++++++++++++++++++++++++++++++++++++++++ //
// Destructor - equivalent to ApplCore CLOSEDOWN. //
// ++++++++++++++++++++++++++++++++++++++++++++++ //
LocalAudio::~LocalAudio()
{
	routerUnregister(car_router);
}


// ++++++++++++++++++++++++++++++++++++++++++++++ //
// All button pushes and notifications come here. //
// ++++++++++++++++++++++++++++++++++++++++++++++ //
void LocalAudio::buttonCallback( buttonNotify *b )
{
	if (b->panel() == PNL_MAIN)
	{
		if (b->id() == 1)		// Is this the source grid button?
		{
			switch (b->value())
			{
				case 0:			// Source is de-selected
					source_selected = false;
					source_index = 0;
					break;

				default:		// A source has been selected
					source_selected = true;
					source_index = b->value().toInt();
					break;
			}

			// Check if we have both a source and destination selected. If so call the auto-take function
			if (source_selected && dest_selected) makeCrosspoint();
			
			return;				// Source Processing finished
		}

		if (b->id() == 2)		// Is this the destination grid button?
		{
			switch (b->value())
			{
				case 0:
					dest_selected = false;
					dest_index = 0;
					break;

				default:
					dest_selected = true;
					dest_index = b->value();
					break;
			}
			// Check if we have both a source and destination selected. If so call the auto-take function
			if (source_selected && dest_selected) makeCrosspoint();

			return;
		}

		if (b->id() == 3)		// Is this the "Clear Selection" button?
		{
			if (source_selected)
			{
				source_index = 0;
				source_selected = false;
				textPut("index", 0, PNL_MAIN, 1);
			}

			if (dest_selected)
			{
				dest_selected = false;
				dest_index = 0;
				textPut("selected", 0, PNL_MAIN, 2);
			}

			return;
		}
	}
}	// End of buttonCallback()

// +++++++++++++++++++++++++ //
// All revertives come here. //
// +++++++++++++++++++++++++ //
int LocalAudio::revertiveCallback( revertiveNotify * r )
{
	if (r->device() == car_router)		// Check for CAR router ID
	{
		textPut("text", r->sInfo(), PNL_MAIN, (11 + r->index() - myFirstOS));
	}

	return 0;
}


// +++++++++++++++++++++++++++++++++++++++++ //
// All database name changes come back here. //
// +++++++++++++++++++++++++++++++++++++++++ //
void LocalAudio::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 LocalAudio::parentCallback( parentNotify *p )
{
	if( p->command() == "return" )
	{
		if( p->value() == "all" )
		{	// Persisting values for bncs_vis_ed
			bncs_stringlist sl;
			
			sl << bncs_string( "myParam=%1" ).arg( m_myParam );
			
			return sl.toString( '\n' );
		}

		else if( p->value() == "myParam" )
		{	// Specific value being asked for by a textGet
			return( bncs_string( "%1=%2" ).arg( p->value() ).arg( m_myParam ) );
		}

	}
	else if( p->command() == "instance" && p->value() != m_instance )
	{	// Our instance is being set/changed
		m_instance = p->value();
		//Do something instance-change related here
	}

	else if( p->command() == "myParam" )
	{	// Persisted value or 'Command' being set here
		m_myParam = p->value();
	}

	// ***** CONNECTIONS EVENTS HELPER LIST *****
	else if( p->command() == "_events" )
	{	// Helper-list of everything in this component generated by hostNotify's
		bncs_stringlist sl;

		sl << "notify=*";		
		
		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 << "myParam=[value]";
		
		return sl.toString( '\n' );
	}

	return "";
}


// +++++++++++++++++++++++ //
// Timer events come here. //
// +++++++++++++++++++++++ //
void LocalAudio::timerCallback( int id )
{
	switch( id )
	{
	case TIMER_TAKE:					// Autoclear selection timer
		timerStop(TIMER_TAKE);
		source_selected = false;			// Clear the selection of the source
		source_index = 0;
		textPut("index", 0, PNL_MAIN, 1);	
		dest_selected = false;				// Clear the selection of the destination
		dest_index = 0;
		textPut("selected", 0, PNL_MAIN, 2);
		break;

	default:	// Unhandled timer event
		timerStop(id);
		break;
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// Callbacks above - Methods below ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// Routine to support making crosspoints when both source and destination are selected. //
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void LocalAudio::makeCrosspoint(void)
{
	// Send the route crosspoint command to the drive
	routerCrosspoint(myLocalAudio, source_index, dest_index);

	// Start timer 1 that will cause the deselection of the sources when it times out
	timerStart(TIMER_TAKE, 300);
}
