/* bncs_auto_helper.cpp - Helper functions for v4.5 Automatics */

#include "bncs_auto_helper.h"
#include <windows.h>

/* TODO:	
1. Add DOXYGEN tags
2. Add implementation for getInstanceSlot
3. Add implementation for gpiPoll
4. Add implementation for gpiQuery
5. Add implementation for gpiSet
6. Add implementation for infoQuery
7. Add implementation for routerQuery
*/




/** get device, slot and type for an instance, parameter pair

\param instance The name of the instance
\param param The name of the parameter
\param *dev Pointer to an integer to return the device number
\param *slot Pointer to an integer to return the slot number
\param *type Pointer to an character to return the device type, for example 'I' for infodriver
\returns true if all OK, otherwise false

\par Example:
\code
	int iDev, iSlot;
	char cType;

	getDevSlot( "ARC1","Input", & iDev, & iSlot, & cType);	// iDev, iSlot and cType will now contain correct information.
	debug("Arc 1 dev=%1, slot=%2, type=%3",iDev, iSlot, cType);

\endcode
*/

bool getDevSlot(bncs_string instance, bncs_string param, int *dev, int *slot, char *type)
{
	bncs_string sType;
	
	int iDevice,iOffset,iSlot;
	char cType;
	
	//check we are being passed valid items
	if (dev==0 || slot==0 || type==0)
	{
		OutputDebugString("bncs_auto_helper~getDevSlot - Invalid vales passed");
		return false;
	}
	
	bncs_config conf( "instances." + instance);
	
	if( !conf.isValid() )
	{
		OutputDebugString("bncs_auto_helper~getDevSlot - Config not valid");
		return false;
	}
	
	bncs_string sComplex = "";
	bncs_string sRef=conf.attr( "ref" );
	bncs_stringlist sl( sRef ,',' );
	for ( int iCount=0; iCount < sl.count() ; iCount++)
	{
		bncs_stringlist sltKeyValue( sl[iCount] ,'=' );
		if (sltKeyValue[0] == "device")
		{
			iDevice = sltKeyValue[1].toInt();
		}
		else if (sltKeyValue[0] == "offset")
		{
			iOffset = sltKeyValue[1].toInt();
		}
		else if (sltKeyValue[0] == "complex")
		{
			sComplex = sltKeyValue[1];
		}
	}
	
	//we now need to find the slot, check device type is valid
	iSlot = 0;
	sType = conf.attr( "type" );
	if( !sType.length())
	{
		OutputDebugString("bncs_auto_helper~getDevSlot - Instance device type not set");
		return false;
	}
	bncs_config confType( "devicetypes\\" + sType );
	
	if( !confType.isValid() )
	{
		OutputDebugString(bncs_string("bncs_script_helper::getDevSlot - device type file '%1' not valid").arg(sType));
		return false;
	}

	//see what type this is, if not specified assume Infodriver
	bncs_string sDevType = confType.attr("drivertype");
	if (sDevType == "GPI")
		cType = 'G';
	else if (sDevType == "ROUTER")
		cType = 'R';
	else
		cType = 'I';

	//we have to go through the file manually to find this parameter
	while (confType.isChildValid())
	{
		if(confType.childAttr("name") == (bncs_string)param)
		{
			iSlot = confType.childAttr("slot").toInt();
			break;
		}
		confType.nextChild();
	}

	if (iSlot == 0)
	{
		//this may be because it is a complex type, so we need to get the data from a complex instance!
		if (sComplex.length())
		{
			iOffset = 0;

			//find the slave instance and parameter, look in the complex_instances/sComplex.xlm file
			bncs_config confComp( bncs_string( "complex_instances\\%1.%2.%3" ).arg( sComplex ).arg(instance).arg(param));
			if (!confComp.isValid())
			{
				OutputDebugString(bncs_string("bncs_auto_helper~getDevSlot - Complex instance file '%1' not valid").arg(sComplex));
				return false;
			}
			bncs_string sBaseInst = confComp.attr("device");
			bncs_string sBaseParam = confComp.attr("param");
			
			if (!getDevSlot(sBaseInst,sBaseParam,&iDevice, &iSlot, &cType))
				return false;
		}
	}

	//we now have the correct numbers to return!
	*dev = iDevice;
	*slot = iSlot + iOffset;
	*type = cType;

	return true;
}
int getInstanceDevice(const bncs_string& strInstance)
{
	bncs_config cfg(bncs_string("instances.%1").arg(strInstance));
	if(cfg.isValid())
	{
		bncs_stringlist sltRef = cfg.attr("ref");
		return sltRef.getNamedParam("device").toInt();
	}
	else 
	{
		return -1;
	}
}

//NEW not ready
//int getDevSlot(const bncs_string& strInstance, bncs_string& strParam )
//{
//	bncs_config cfg(bncs_string("instances.%1").arg(strInstance));
//	if(cfg.isValid())
//	{
//		bncs_stringlist sltRef = cfg.attr("ref");
//		int intOffset = sltRef.getNamedParam("offset").toInt();
//		int intParamSlot = 0; //TODO
//		return intOffset + intParamSlot;	
//	}
//	else 
//	{
//		return -1;
//	}
//}

/*
Function:
	getObjectSetting

Description:
	Return named setting for this object (from object_settings.xml) 

Parameters:
	strObject  the name of the object to get information about  
	strSetting  name of setting to return  

Returns:
	object setting or null string if not found
        bncs_string strSetting = getObjectSetting( "myObject", "mySetting" );  
        // s contains the "mySetting" setting of the "myObject" object
*/
bncs_string getObjectSetting(const bncs_string& strObject, const bncs_string& strSetting)
{
	bncs_config cfg(bncs_string("object_settings.%1.%2").arg(strObject).arg(strSetting));
	bncs_string strValue = "";
	if(cfg.isValid())
	{
		strValue = cfg.attr("value");
	}
	return strValue;
}

/* 
Function:
	getRouterSize
Description:
   	Return the size of a device from its device settings file 

Parameters:
	intDevice  	The device number  
	intSwitch	The database number (0 or 1)  

Returns:
	the size of the database
        
Example:        
        int intSize = getRouterSize( 123, 1 );                
        // intSize contains the number of destinations in the database for device 123

*/
int getRouterSize(int intDevice, int intSwitch) 
{
	char szFileName[32];
	char szKey[32];
	sprintf(szFileName, "dev_%03d.ini", intDevice);
	sprintf(szKey, "DatabaseSize_%d", intSwitch);
	int intSize = 0;
	// to do ---- sort out declaration of r_p   
	intSize=atoi(r_p(szFileName, "Database", szKey, "0"));
	return intSize;
}

char* r_p(char* file, char* section, char* entry, char* defval)
{
	char szPath[256];          
	char* szCCRoot = getenv( "CC_ROOT" );
	char* szCCSystem = getenv( "CC_SYSTEM" );
static	char szResult[256];
	
	if(szCCRoot && szCCSystem){
		//sprintf(szPath, "%s\\%s\\system\\config\\%s", szCCRoot, szCCSystem, file);
		//NOTE: replace the above line with the one below when V4CSI is fixed
		sprintf(szPath, "%s\\%s\\config\\system\\%s", szCCRoot, szCCSystem, file);
	}
	else {
		strcpy(szPath, file);
	}
	
	GetPrivateProfileString(section, entry, defval, szResult, sizeof(szResult), szPath);
  // strcpy(szPath, file);
	//	w_p(file,section,entry,szResult);
	
	return szResult;
}




/*
Function:
	getWorkstationSetting

Description:
	Return named setting for this workstation 

Parameters:
	strSetting  	name of setting to return  

Returns:
	workstation setting or null string if not found

Example:        
        bncs_string strSetting = getWorkstationSetting( "intSDIDestMon" );      
        // strSetting contains the "intSDIDestMon" setting
*/


/*  ALL REST COMMENTED OUT UNTIL THEY WORK -- -- PAW



bncs_string getWorkstationSetting(const bncs_string& strSetting)
{
	//TODO check workstation() call is correct
	////// correct this line   ////// bncs_config cfg(bncs_string("workstation_settings.%1.%2").arg(workstation()).arg(strSetting));
	bncs_string strValue = "";
	if(cfg.isValid())
	{
		strValue = cfg.attr("value");
	}
	return strValue;
}

//void gpiPoll(int intDevice, int intMin, int intMax){}
//void gpiQuery(int intDevice, int intMin, int intMax){}
//void gpiSet(int intDevice, int intIndex, int intValue){}


void infoPoll(int intDevice, int intMin, int intMax)
{
	bncs_string strCmd = bncs_string("IP %1 %2 %3").arg(intDevice).arg(intMin).arg(intMax);
	ec.txinfocmd(strCmd);
}

//void infoQuery(int intDevice, int intMin, int intMax){}
void infoWriteInt(int intDevice, int intValue, int intIndex)
{
	bncs_string strCmd = bncs_string("IW %1 '%2' %3").arg(intDevice).arg(intValue).arg(intIndex);
	ec.txinfocmd(strCmd);
}

void infoWriteString(int intDevice, const bncs_string& strValue, int intIndex)
{
	bncs_string strCmd = bncs_string("IW %1 '%2' %3").arg(intDevice).arg(strValue).arg(intIndex);
	ec.txinfocmd(strCmd);
}

void routerCrosspoint(int intDevice, int intSource, int intDest, const bncs_string& strMask)
{
	bncs_string strCmd = bncs_string("RC %1 %2 %3").arg(intDevice).arg(intSource).arg(intDest).arg(strMask);
	ec.txinfocmd(strCmd);
}

void routerPoll(int intDevice, int intMin, int intMax)
{
	bncs_string strCmd = bncs_string("RP %1 %2 %3").arg(intDevice).arg(intMin).arg(intMax);
	ec.txinfocmd(strCmd);
}

//void routerQuery(int intDevice, int intMin, int intMax){}

  */