int ProgramManager::StartProgram( int programId )
{
	if ( this->runningPrograms[programId] != NULL )
	{
		EventLogger::Instance()->WriteVerbose(
				"Program with id '%d' is already started.", programId );
		return ERROR_PRSTARTED_ID;
	}

	string upcbDescriptor = this->availablePrograms[ programId ];
	string upcbProgramMapping = this->programMappings[ programId ];

	if ( upcbDescriptor == "" )
	{
		EventLogger::Instance()->WriteVerbose(
				"The program with id - '%d' is not available.", programId );
		return ERROR_PRNOTFOUND_ID;
	}
	if ( upcbProgramMapping == "" )
	{
		EventLogger::Instance()->WriteVerbose(
				"The program mappings for program with id %d are not available.",
				programId );
		return ERROR_NOMAPPING_ID;
	}

	Program* program = UpcbJsonParser::Instance()->ParseProgram( upcbDescriptor );

	if ( program == NULL )
	{
		EventLogger::Instance()->WriteVerbose(
				"The program with id - %d could not be created from the given description.",
				programId );
		return ERROR_LOADINGERROR_ID;
	}

	// Initialize program mappings:
	ProgramMapping* mapping = UpcbJsonParser::Instance()->ParseProgramMapping( upcbProgramMapping );
	MappingManager::Instance()->InitializeProgram( program, mapping->PinoutMappings() );
	Process* newProcess = new Process();
	newProcess->RegisterErrorHandler( this );
	newProcess->Start( program );

	this->runningPrograms[programId] = newProcess;

	EventLogger::Instance()->WriteVerbose(
		"The program with id - %d was successfully started.",
		programId );
	return 0;
}
void ProgramManager::AddProgramMapping( string json )
{
	ProgramMapping* mapping = UpcbJsonParser::Instance()->ParseProgramMapping( json );
	this->programMappings[ mapping->ProgramId() ] = json;

	//delete mapping;

	//Save Program & Mapping:
	string storageFolderPath = Configuration::Instance()->GetStringParam( PROGRAMS_STORAGE_DIR );

	struct stat st;
	if ( stat( storageFolderPath.c_str(), &st ) != 0 )
		mkdir( storageFolderPath.c_str(), 0777 );

	string mappingSavePath = storageFolderPath + "/" + mapping->ProgramName() + "_mapping.xml";
	DataSerializationManager::Save( json, mappingSavePath.c_str() );
}
ProgramMapping* UpcbJsonParser::ParseProgramMapping( string json )
{
	int i;
	size_t endIndex;

	size_t startFrom = 0;
	size_t start;
	size_t end;

	size_t temp;
	size_t index;
	int id;

	string commandsArray;
	string deviceId;
	string driverType;
	string eventsAray;
	string pinoutId;

	// Get Program Id
	i = json.find( JsonParameters::ProgramId );
	start = i + JsonParameters::ProgramId.size() + 2;
	index = json.find( JsonParameters::ProgramName );
	startFrom = json.find( JsonParameters::Mapping );

	end = index - 2;
	id = atoi( json.substr( start, end - start ).c_str() );

	start = index + JsonParameters::ProgramName.size() + 3;
	end = startFrom - 3;

#ifndef PROFILE
	ProgramMapping* mapping = new ProgramMapping( id, json.substr( start, end - start ) );
#else
	ProgramMapping* mapping = NULL;
#endif

	while ( true )
	{
		index = json.find( JsonParameters::Commands, startFrom );
		if ( index == string::npos)
			break;

		startFrom = index + 1;

		temp = json.find( JsonParameters::DeviceId, startFrom );

		// commandsIndex + [CommandParamName]  + ":
		start = index + JsonParameters::Commands.size() + 2;
		end = temp - 2;
		commandsArray = json.substr( start, end - start );

		start = temp + JsonParameters::DeviceId.size() + 2;
		temp = json.find( JsonParameters::Driver, startFrom );
		end = temp - 2;
		deviceId = json.substr( start, end - start );

		start = temp + JsonParameters::DriverType.size() + 3; // ":"
		temp = json.find( JsonParameters::Events, startFrom );
		end = temp - 3;
		driverType = json.substr( start, end - start );
		start = temp + JsonParameters::Events.size() + 2; // ":


		temp = json.find( JsonParameters::PinoutId, startFrom );
		endIndex = json.find( "}", temp );
		end = temp - 2;
		eventsAray = json.substr( start, end - start );

		start = temp + JsonParameters::PinoutId.size() + 2;
		end = endIndex;
		pinoutId = json.substr( start, end - start );

#ifndef PROFILE
		PinoutMapping* pinoutMapping = new PinoutMapping(atoi( pinoutId.c_str() ), atoi( deviceId.c_str() ), driverType);
#else
		PinoutMapping* pinoutMapping = NULL;
#endif

		i = 0;

		// Parse the commands
		this->ParseUpcbCommands( commandsArray, pinoutMapping );
		//Parse the events
		this->ParseUpcbEvents( eventsAray, pinoutMapping );

#ifndef PROFILE
		mapping->PinoutMappings()->push_back( pinoutMapping );
#endif
	}

	return mapping;
}