#include "GenSimulation.h"

using namespace std;

static GenSimulation * simulation = NULL;

//////////////////////////////////////////////////////////////////////
// Get the instance of the Cell Simulation
// ->	Only allow one instance of the cell to exist at any one time
// 		If not yet exist, create a new Cell Simulation
// 		otherwise return the pointer to the current existing Cell Simulation
//
GenSimulation * GenSimulation::getSimulation(){
	// If the simulation cell Simulation not yet exist
	if(!isInstantiated){
		// Create new Cell Simulation
		simulation = new GenSimulation();
		// New Cell Simulation Created
		isInstantiated = true;
	}
	// Return the pointer to the current Cell Simulation
	return simulation;
}



//////////////////////////////////////////////////////////////////////
// Constructor for the GenSimulation
// ->	Create and initialize properties of the GenSimulation space
GenSimulation::GenSimulation():Simulation(){

	// Initialize Simulation
	initialDataInput();
}



//////////////////////////////////////////////////////////////////////
// Destructor for the GenSimulation
//
GenSimulation:: ~GenSimulation(){}



//////////////////////////////////////////////////////////////////////
//  Input of molecules to the GenSimulation Space
//  (number of molecules, molecule type, environment)
//
void GenSimulation::initialDataInput(){

	createMolecule(getI("NUM_MOL_ENZYME_B"), MOL_ENZYME_B, lEnv->firstEnv(MOL_ENZYME_B));
	

#ifdef CALCIUM_ION_CHANNELS
	int maxX = (xDim + 1) / 10;
	int maxY = (yDim + 1) / 10;

	bool first = true;

	for (int x = 0; x < maxX; x++) {
		for (int y = 0; y < maxY; y++) {
			for (int i = 0; i < 2; i++) {
				int xIdx = RandomNG::randInt(x*10+1,x*10+9);
				int yIdx = RandomNG::randInt(y*10+1,y*10+9);

				Point * loc = new Point( xIdx, yIdx, 4 );

				MembranousMolecule * m = new MembranousMolecule;

				m->type = MOL_MEMBRANOUS_FIXED_PUMP;
				m->setPosition( *loc );
				m->setDiffusible( false );

				memMolTable[m->type].push_back(m);
				delete loc;

				xIdx = RandomNG::randInt(x*10+1,x*10+9);
				yIdx = RandomNG::randInt(y*10+1,y*10+9);

				loc = new Point( xIdx, yIdx, 4 );

				m = new MembranousMolecule;

				m->type = MOL_MEMBRANOUS_FIXED_GATE;

				if (first) {
					m->state = GATE_IS_OPEN;
					m->openedAt = 0;
					first = false;
				}
				else {
					m->state = GATE_IS_CLOSED;
					m->openedAt = -1;
				}

				m->setPosition( *loc );
				m->setDiffusible( false );

				memMolTable[m->type].push_back(m);
				delete loc;
			}
		}
	}
#endif
}



//////////////////////////////////////////////////////////////////////
//  Create Molecule where following are specified
//  type: the type of molecule to create
//
Molecule * GenSimulation::createNewMolecule(int type){

		return new Enzyme(type);
}



//////////////////////////////////////////////////////////////////////
//  Perform periodic modifications to the GenSimulation Space
//  ->	Temporal events updating behaviour/Properties of the GenSimulation
//
void GenSimulation :: updateSimulation(){


}



bool GenSimulation :: isSimulationCompleted(){

	return simulationCompleted;
}




//////////////////////////////////////////////////////////////////////
//  Display data collected from the Simulation
//
void GenSimulation :: displayResults(){
	map< string , int >::const_iterator itr = actEventTable.begin();
	
	for (itr = actEventTable.begin(); itr != actEventTable.end(); itr ++) 
	{
		printf("~\t%s\t%d\n", (itr->first).c_str(), itr->second);
	}
	
	// Display total number of cycles to complete simulation
	printf("#\tTotal num of cycles\t%d\n",numCycles);
}
