#ifndef SIMULATION_H
#define SIMULATION_H

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <fstream>
#include <vector>
#include <map>

#include "definition.h"
#include "LatticeEnvironment.h"
#include "Molecule.h"
#include "MembranousMolecule.h"
#include "Enzyme.h"
#include "LatticeSite.h"
#include "ParameterManager.h"
#include "Point.h"


using namespace std;

class Simulation
{

	public:
	
		// Static Variables and Operations
		// The Status of the Cell Lattice
		static bool isInstantiated;
		// Pointer to the Cell Lattice
		static Simulation * sim;
		
		//////////////////////////////////////////////////////////////////////
		// Static Operations on the Lattice
		// Get an instance of the Simulation
		//static Simulation * getSimulation();
		
		//////////////////////////////////////////////////////////////////////
		// Public Operations on Simulation
		
		// Start Simulation
		void simulate();
		
		// Continue Simulation
		void continueSimulation();
		
		// Create Molecule within the Simulation Space (num, type, env)
		void createMolecule(int, int, int);
		
		// Remove specified Molecule from the Simulation Space
		void remove(Molecule *);
		
		// Display/output details of Interaction events (activator, activatee, [1|0])
		void printInteractionDetails(Molecule *, Molecule *, moltype);
		
		// Get current number of cycles executed (Time unit)
		int getCycles();
		
		// Get number of molecules existing in the Simulation Space
		int getNumMolecules();
		
		// Get number of molecules of the specifed type in the Simulation Space (type)
		int getNumMolecules(moltype);
		
		// Access the Molecule Table that contains all moelcules in the Simulation
		map <moltype, vector <Molecule *> > * getMoleculeTable();
		
		// Access the Molecule Table that contains all moelcules in the Simulation
		map <moltype, vector <MembranousMolecule *> > * getMembranousMoleculeTable();
		
		// Is Simulation completed
		virtual bool isSimulationCompleted();

	protected:
		//////////////////////////////////////////////////////////////////////
		// Constructor and Destructor of the Lattice
		Simulation();
		virtual ~Simulation();

		

		//////////////////////////////////////////////////////////////////////
		// Member variables
		
		// Number of Molecules in the Simulation
		int numMolecules;
		
		// Number of cycles executed (Time unit)
		int numCycles;
		
		// flag for Simulation completion
		bool simulationCompleted;

		// Number of activated cut sites- added by Adam
		int cutSitesActive;		

		// Table of intracellular molecules in the simulation grouped by type
		map <moltype, vector <Molecule *> > molTable;

		// Table of membranous molecules in the simulation, grouped by type
		map <moltype, vector <MembranousMolecule *> > memMolTable;
		
		// Molecule Activation Table (type <-> list of types)
		map <moltype, vector <moltype> > interactionNetworkTable;
		
		// Table of manages activation events (name <-> num activated)
		map <string, int> actEventTable;

		map <moltype, vector <Point *> > molSitesTable;		

		// Environment Manager
		LatticeEnvironment * lEnv;
		
		//////////////////////////////////////////////////////////////////////
		// Private Operations
		
		// Input Data
		virtual void initialDataInput() = 0;
		
		// Display data from simulation
		virtual void displayResults() = 0;
		
		virtual Molecule * createNewMolecule(int) = 0;
		
		// Periodically update Behaviour/Properties
		virtual void updateSimulation();
		
		// Display all Molecules in the Simulation
		void display();

		// Sumarize all the Molecules in the Simulation
		void summary();

		// Add Molecules to the Simulation
		void add(Molecule *);
		
		// Build a table that represents the Molecule Interaction Network
		void buildInteractionNetworkTable();
		
		// Molecules move/diffuse randomly
		void move();

		// Transport molecules across a membrane through channels, etc.
		void transportAcrossMembranes();

		// Check molecules interaction
		void checkMoleculeInteractions();

		void checkEnzymaticReactions();
		
		// Interact with neighboring molecules
		void interactNeighborMolecules(Molecule *);
		
		// Build a list of neigboring molecules of the specified molecule
		vector <Molecule *> buildNeighborList(Molecule *);
		
		// Get the activation/interaction list of a specific type of molecule
		vector <moltype> getInteractionTypeList(moltype);
		
		// Inject molecules - added by Adam
		void inject();

}
;

#endif
