#include <windows.h>
#include <stdio.h>
#include <bncs_string.h>
#include <bncs_config.h>
#include "GPItest.h"

#define MAIN_PANEL	1
#define PANEL_NAME "GPItest.bncs_ui"

#define TIMER_SETUP	1
#define FIRST_OUT 1
#define FIRST_IN 101
#define NUM_OUT 64
#define NUM_IN 48

#define GPI_DRIVER_ID 675

// Macro to make our class visible to the outside world
EXPORT_BNCS_SCRIPT( GPItest )

// Constructor - equivalent to ApplCore STARTUP
GPItest::GPItest( bncs_client_callback * parent, const char * path ) : bncs_script_helper( parent, path )
{
	bncs_string btn_txt;

	// Show our panel
	panelShow(MAIN_PANEL, PANEL_NAME);

	// Clear the output status array
	for (int i = 0; i < NUM_OUT+1; i++) outstate[i] = false;

	// Need to add names to the buttons. Names are held in objects_settings.xml, object id="CTA_GPI_RACK"
	// The in and out names have object names such as "In_101" and "Out_01". The value returns the name.
	for (int i = FIRST_OUT; i <= NUM_OUT; i++)
	{
		btn_txt = getObjectSetting("CTA_GPI_RACK", bncs_string("Out_%1").arg(i, '0', 2, 10));
		btn_txt += bncs_string("|Out %1").arg(i, '0', 2, 10);
		textPut("text", btn_txt, MAIN_PANEL, bncs_string("Out_%1").arg(i, '0', 2, 10));
	}

	for (int i = FIRST_IN; i < (FIRST_IN + NUM_IN); i++)
	{
		btn_txt = getObjectSetting("CTA_GPI_RACK", bncs_string("In_%1").arg(i, '0', 2, 10));
		btn_txt += bncs_string("|In %1").arg(i, '0', 2, 10);
		textPut("text", btn_txt, MAIN_PANEL, bncs_string("In_%1").arg(i, '0', 2, 10));
	}

	// Show the main label.
	textPut("text", bncs_string("BNCS Driver %1").arg(GPI_DRIVER_ID), MAIN_PANEL, "GPI_Driver_Id");

	// Register for revertives from the GPI driver, and poll for current status
	gpiRegister(GPI_DRIVER_ID, FIRST_OUT, (FIRST_IN + NUM_IN));
	gpiPoll(GPI_DRIVER_ID, FIRST_OUT, FIRST_OUT + NUM_OUT - 1);
	gpiPoll(GPI_DRIVER_ID, FIRST_IN, FIRST_IN + NUM_IN - 1);
}

// destructor - equivalent to ApplCore CLOSEDOWN
GPItest::~GPItest()
{
	gpiUnregister(GPI_DRIVER_ID);
}

// all button pushes and notifications come here
void GPItest::buttonCallback( buttonNotify *b )
{
	if (b->panel() == MAIN_PANEL)
	{
		if (b->id().startsWith("Out_"))
		{
			int ix;
			bool newState;
			ix = b->id().firstInt();
			newState = (outstate[ix] == 0) ? true : false;	// Toggle the state
			gpiSwitch(GPI_DRIVER_ID, newState, ix, true);
		}
	}
}

// all revertives come here
int GPItest::revertiveCallback( revertiveNotify * r )
{
	int idx;
	bncs_string mimicState;

	if (r->device() == GPI_DRIVER_ID)
	{
		idx = r->index();
		mimicState = (r->info() == 0) ? "destgroup_deselected" : "alarm_alarm";

		if ((idx >= FIRST_OUT) && (idx <= (FIRST_OUT + NUM_OUT - 1)))
		{
			// Record new output state, and update the mimic
			outstate[idx] = r->info();
			textPut("statesheet", mimicState, MAIN_PANEL, bncs_string("Out_%1").arg(idx, '0', 2, 10));
		}

		if ((idx >= FIRST_IN) && (idx <= (FIRST_IN + NUM_IN - 1)))
		{
			// Set input mimic state
			textPut("statesheet", mimicState, MAIN_PANEL, bncs_string("In_%1").arg(idx, '0', 3, 10));
		}

	}
	
	return 0;
}

// all database name changes come back here
void GPItest::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 GPItest::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 GPItest::timerCallback( int id )
{
	switch( id )
	{
	case TIMER_SETUP:
		timerStop(id);
		break;

	default:	// Unhandled timer event
		timerStop(id);
		break;
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// Callbacks above - Methods below ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////


