Program* UpcbJsonParser::ParseProgram( string json )
{
	size_t idIndex;
	size_t programDescrIndex;
	size_t devicesIndex;
	size_t nameIndex;
	size_t powerwireIndex;
	size_t wiresIndex;
	size_t devTypeIndex;
	size_t devPropsIndex;

	size_t start, end;
	size_t startIndex = 0;
	size_t startFrom = 0;
	size_t bracketIndex = 0;
	size_t keyIndex;
	size_t valueIndex;
	size_t typeIndex;

	string id;
	string programDescription;
	string devices;
	string name;
	string powerWire;
	string wires;
	string deviceType;
	string deviceProperties;
	string cpId;
	string propertyKey;
	string propertyValue;
	string propertyType;

	idIndex = json.find( JsonParameters::Id );
	programDescrIndex = json.find( JsonParameters::ProgramDescription );
	devicesIndex = json.find( JsonParameters::Devices );
	nameIndex = json.find( JsonParameters::Name );
	powerwireIndex = json.find( JsonParameters::PowerWire );
	wiresIndex = json.find( JsonParameters::Wires );

	start = idIndex + JsonParameters::Id.size() + 2; //":
	end = programDescrIndex - 2;
	id = json.substr( start, end - start );

	start = programDescrIndex + JsonParameters::ProgramDescription.size() + 3; //":"
	end = devicesIndex - 3;
	programDescription = json.substr( start, end - start );

	start = devicesIndex + JsonParameters::Devices.size() + 3; //":[
	end = nameIndex - 3;
	devices = json.substr( start, end - start );

	start = nameIndex + JsonParameters::Name.size() + 3; //":"
	end = powerwireIndex - 3;
	name = json.substr( start, end - start );

	start = powerwireIndex + JsonParameters::PowerWire.size() + 3;
	end = wiresIndex - 3;
	powerWire = json.substr( start, end - start );

	start = wiresIndex + JsonParameters::Wires.size() + 3;
	end = json.size() - 2;
	wires = json.substr( start, end - start );

#ifndef PROFILE
	Program* program = new Program( atoi( id.c_str() ), name, programDescription );
#else
	Program* program = NULL;
#endif

	BaseDevice* device;
	ConnectionPoint* connPoint;

	// Resolve Devices:
	while ( true )
	{
		idIndex = devices.find( JsonParameters::Id, startIndex );
		if ( idIndex == string::npos)
			break;

		devTypeIndex = devices.find( JsonParameters::DeviceType, startIndex );
		devPropsIndex = devices.find( JsonParameters::DeviceProperties, startIndex );

		start = idIndex + JsonParameters::Id.size() + 2;
		end = devTypeIndex - 2;
		id = devices.substr( start, end - start );

		start = devTypeIndex + JsonParameters::DeviceType.size() + 3;
		end = devPropsIndex - 3;
		deviceType = devices.substr( start, end - start );
#ifndef PROFILE
		device = DeviceManager::Instance()->GetDevice( deviceType.c_str() );
		if( device == NULL )
		{
			// LOG !
			return NULL;
		}

		device->SetId( atoi( id.c_str() ) );
		program->AddDevice( device );
#endif
		start = devPropsIndex + JsonParameters::DeviceProperties.size() + 2;
		end =  devices.find( ']', devPropsIndex ) + 1;
		deviceProperties = devices.substr( start, end - start );

		startFrom = 0;
		startIndex = end + 1;

		while( true )
		{
			bracketIndex = deviceProperties.find( '}', startFrom );
			if( bracketIndex == string::npos )
				break;

			keyIndex = deviceProperties.find( JsonParameters::DevicePropertyKey, startFrom );
			valueIndex = deviceProperties.find( JsonParameters::DevicePropertyValue, startFrom );
			typeIndex = deviceProperties.find( JsonParameters::DevicePropertyType, startFrom );

			start =  keyIndex + JsonParameters::DevicePropertyKey.size() + 3; // ":"
			end = valueIndex - 3;
			propertyKey = deviceProperties.substr( start, end - start );

			start =  valueIndex + JsonParameters::DevicePropertyValue.size() + 3;
			end = typeIndex - 3;
			propertyValue = deviceProperties.substr( start, end - start );

			start =  typeIndex + JsonParameters::DevicePropertyType.size() + 3;
			end = bracketIndex - 1;
			propertyType = deviceProperties.substr( start, end - start );

			string * valueString = new string(propertyValue);

			DeviceParameter* prop = new DeviceParameter( propertyKey, propertyType, propertyValue );
#ifndef PROFILE
			device->AddCustomProperty( prop );
			device->SetParameter(propertyKey, (void *)valueString);
#endif

			startFrom = bracketIndex + 1;
		}
	}

	//Resolve the Power wire
	int cpArrayIndex;
	string connPoints;
	int cpIdIndex, deviceIdIndex;
	string cpElement;

	//Resolve Wires
	startIndex = 0;
	while ( true )
	{
		startFrom = 0;
		cpArrayIndex = wires.find( JsonParameters::ConnectionPoints, startIndex );
		if ( cpArrayIndex == string::npos )
			break;

		startIndex = cpArrayIndex + 1;
		start = cpArrayIndex + JsonParameters::ConnectionPoints.size() + 3;
		end = wires.find( ']', startIndex );

		connPoints = wires.substr( start, end - start );
#ifndef PROFILE
		Wire* wire = new Wire();
#endif
		while ( true )
		{
			bracketIndex = connPoints.find( '}', startFrom );
			if ( bracketIndex == string::npos )
				break;

			cpElement = connPoints.substr( startFrom, bracketIndex - startFrom );
			startFrom = bracketIndex + 1;

			cpIdIndex = cpElement.find( JsonParameters::ConnectionPointId );
			deviceIdIndex = cpElement.find( JsonParameters::DeviceId );

			start = cpIdIndex + JsonParameters::ConnectionPointId.size() + 2;
			end = deviceIdIndex - 2;
			cpId = cpElement.substr( start, end - start );

			start = deviceIdIndex + JsonParameters::DeviceId.size() + 2;
			end = cpElement.size();
			id = cpElement.substr( start, end - start );
#ifndef PROFILE
			device = program->GetDevice( atoi( id.c_str() ) );
			connPoint = device->GetConnectionPoint( atoi( cpId.c_str() ) );

			wire->Attach( connPoint );
#endif
		}
#ifndef PROFILE
		program->Wires()->push_back( wire );
#endif
	}

	return program;
}
Program* ProgramManager::CreateFromDescriptor( ProgramDescriptor* descriptor )
{
	int id;
	string name;
	string description;

	DescriptorsUtil::GetIntProperty( descriptor->Properties, "Id", &id );
	DescriptorsUtil::GetStringProperty( descriptor->Properties, "Name", &name );
	DescriptorsUtil::GetStringProperty( descriptor->Properties, "Description",
			&description );

	Program* program = new Program( id, name, description );
	string deviceType;
	// ------ Initialize Devices:
	list<DeviceDescriptor>::iterator deviceIt;
	for ( deviceIt = descriptor->Devices.begin(); deviceIt
			!= descriptor->Devices.end(); deviceIt++ )
	{
		BaseDevice* device = DeviceManager::Instance()->CreateFromDescriptor(
				*deviceIt );

		if( device == NULL )
			return NULL;

		program->AddDevice( device );
	}
	// ------- Initialize Wires:
	list<WireDescriptor>::iterator wireIt;
	list<WireConnectionPointDescriptor>::iterator cpIt; //connectionPointsIt

	for ( wireIt = descriptor->Wires.begin(); wireIt != descriptor->Wires.end(); wireIt++ )
	{
		Wire* wire = new Wire();

		for ( cpIt = ( *wireIt ).WireConnectionPoints.begin(); cpIt
				!= ( *wireIt ).WireConnectionPoints.end(); cpIt++ )
		{
			BaseDevice* device = program->GetDevice(
					( *cpIt ).DeviceDescriptorId );
			ConnectionPoint* cp = device->GetConnectionPoint(
					( *cpIt ).ConnectionPointDescriptorId );

			wire->Attach( cp );
		}

		program->AddWire( wire );
	}

	// ------ Initialize the program's Power Wire:
	list<WireConnectionPointDescriptor>* stratupPoints =
			&descriptor->PowerWire.WireConnectionPoints;
	for ( cpIt = stratupPoints->begin(); cpIt != stratupPoints->end(); cpIt++ )
	{
		int* startUpValue = new int( 1 );

		BaseDevice* device = program->GetDevice( ( *cpIt ).DeviceDescriptorId );
		ConnectionPoint* cp = device->GetConnectionPoint(
				( *cpIt ).ConnectionPointDescriptorId );

		InConnectionPoint* inConnectionPoint = (InConnectionPoint*) cp;
		inConnectionPoint->SetValue( startUpValue );

		program->PowerWire()->Attach( inConnectionPoint );
	}

	return program;
}