/*
   Project: Adun

   Copyright (C) 2005 Michael Johnston & Jordi Villa-Freixa

   Author: Michael Johnston

   Created: 2005-06-23 11:06:55 +0200 by michael johnston

   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#ifndef SPHERICAL_BOX
#define SPHERICAL_BOX

#include <stdbool.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include "Base/AdVector.h"
#include "Base/InterTable.h"
#include "Base/AdQuaternion.h"
#include "AdunKernel/AdDataSources.h"
#include "AdunKernel/AdGridDelegate.h"
#include "AdunKernel/AdDelegation.h"
#include "AdunKernel/AdunDefinitions.h"
#include "AdunKernel/AdunGrid.h"

/**
SphericalBox creates and manages a collection of molecules of a given type in a spherical
volume. The type of molecule and its topology is defined by the dataSource which must
conform to the AdSystemDataSource protocol. SphericalBox
creates the collection by using an AdGrid instance to create a (cartesian) grid inside the volume.
The number of molecules to be placed in the volume is calculated from the density parameter.
Once the number of molecules is known SphericalBox replecates the information in its dataSource
that many times and uses the grid points created by AdGrid as initial positions for the molecules.
The molecules are randomly oriented when first placed.

SphericalBox conforms to AdSystemDataSource and forms the basis of solvent systems in Adun.
Aswell as creating a solvent system it also provides methods that allow you to insert and
extract other systems into/from the solvent volume eliminating and creating solvent molecules as 
necessary.

\todo We can refactor the non grid delegate parts to the superclass
and then subclasses can just implement the grid delegate methods
\todo Move expandInterTable code to a function in Base
\todo Calculate the grid spacing correctly
\todo Provide a more complete initialiser: initWithEnvironment:density:dimensions
\bug Environment observation - variable dependants not updated 
\bug Dependants dict not encoded - Have to decided wheather this is the correct mechanism for dependant variable
updating.
\todo Check how changing the system radius, speacing density etc would work
\todo Check obscured molecule maintainence
\ingroup Cinter
**/

@interface SphericalBox: AdObject <AdSystemDataSource, AdDataSourceDelegation, AdGridDelegate, AdMemento>
{
	@private
	BOOL memento;
	int seed;
	gsl_rng* twister;
	id dataSource;
	//sphere variables
	double sphereRadius;		//!< the radius of the sphere
	double sphereVolume;		//!< the volume of the sphere
	double solventDensity;		//!< the target solvent density
	double solventMass;		//!< the mass of the solvent
	Vector3D sphereCentre;
	NSArray* sphereExtremes;
	//grid variables 
	id solventGrid;			//!< the grid matrix
	//Solvent System variables		
	int totalNumberOfMolecules;	//!< the total no of molecules that would be in a pure solvent sphere
	int totalNumberOfAtoms;		//!< the total no of atoms that would be in a pure solvent sphere
	int currentNumberOfMolecules;	//!< the no of molecules that are currently in the sphere
	int currentNumberOfAtoms;	//!< the no of atoms that are currently in the sphere
	int no_obscured_molecules;	//!< the number of solvent molecules hidden by the solute
	int atomsPerMolecule;		//!< the number of atoms in a solvent molecule
	AdMatrix *solventCoordinates;		//!< the complete solvent atom coordinates
	AdMatrix *currentSolventCoordinates;	//!< the coordinates of the molecules not obscured
	NSMutableArray* solventAtomTypes;
	NSMutableDictionary* solventBondedInteractions;
	NSMutableArray* solventNonbonded;
	NSMutableDictionary* solventNonbondedTypes;
	NSMutableIndexSet* obscuredIndexes;	
	NSString* currentCaptureMethod;
	id memoryManager;
}
-(void) hideMoleculesWithIndexes: (NSIndexSet*) indexes;
- (void) setExclusionPoints: (AdMatrix*) exclusionPoints exclusionRadius: (double) exclusionRadius;
- (NSValue*) coordinates;
- (int) atomsPerMolecule;
- (int) numberOfAtoms;
- (int) numberOccludedMolecules;

@end

#endif
