/*
   Project: UL

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

   Author: Michael Johnston

   Created: 2005-05-23 18:32:14 +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 _ULSYSTEMBUILDER_H_
#define _ULSYSTEMBUILDER_H_

#include <Foundation/Foundation.h>
#include <AdunKernel/AdunDataSource.h>
#include "ULFramework/ULIOManager.h"
#include "ULFramework/ULConfigurationBuilder.h"
#include "ULFramework/ULTopologyFrameBuilder.h"
#include "ULFramework/ULInteractionsBuilder.h"
#include "ULFramework/ULMerger.h"
#include "ULFramework/ULSimpleMergerDelegate.h"

/**
Class that creates systems for simulation based on the Builder pattern.
It is composed of four seperate parts which are instances of 
ULConfigurationBuilder, ULTopologyFrameBuilder, ULMerger & ULInteractionsBuilder (or one of their subclasses) 
respectively. 
ULSystemBuilder is like an assembly line with each object performing a
different task in the production of a complete system.


\todo Add system builder error codes and domain.
\ingroup classes

*/

@interface ULSystemBuilder : NSObject
{
	NSError* internalError;
	NSString* internalString;
	ULIOManager* ioManager;
	id configurationBuilder;	//!< ULConfigurationBuilder subclass
	id topologyFrameBuilder;	//!< ULTopologyFrameBuilder subclass
	id interactionsBuilder;		//!< ULInteractionsBuilder subclass
	id merger;			//!< ULMerger subclass
	AdDataSource* system;		//!< The last fully created system
	id configuration;		//!< The last built configuration
	id topologyFrame;		//!< The last built topology frame
	NSString* buildPosition;	//!< Where the builder is on the pathway
	NSString* forceField;
	NSString* fileType;
	NSArray* availableForceFields;
	NSArray* knownFileTypes;
	id mergerDelegate;
}

/**
Returns a new ULSystemBuilder initialises to process molecules of type /e fileType using the force field
/e forceFieldName
\param fileType The type of file ULSystemBuilder is to process
\param forceFieldName The force field to be used
\return A new ULSystemBuilder instance
*/
- (id) initWithFileType: (NSString*) configurationPluginName forceField: (NSString*) forceFieldName;

/**
Builds the \e partName section of the system. \e partName can be "Configuration", "Topology", "Merger" or
"Interactions" each of which is a step on the build pathway.
They must be called in this order e.g. calling this method with \e partName = "Topology" before
having called with partName = "Configuration" is an error. The pathway has single occupancy and is unidirectional.  
\param partName The section of the system to be built. ("Configuration", "Topology", "Merger", "Interactions")
\param optionsDict Options controlling each build. See the individual builder documentation for more info
\param error A pointer to an NSError object. Any errors in the build step will be put here
\param info A pointer to a string object. Information on the build step will be put here
\note The functionality may be expanded to enable multiple systems at different parts of the pathway.
*/
- (void) buildPart: (NSString*) partName 
		options: (NSDictionary*) optionsDict 
		error: (NSError**) buildError
		userInfo: (NSString**) buildInfo;
/** 
Sets the molecule that ULSystemBuilder will convert into a system
\param path The path to the molecule
Will raise an exception if the molecule is not of the same file type the object has been set to process
*/
- (void) setBuildMolecule: (NSString*) path;
/**
Returns the path to the molecule file last set by
setBuildMolecule:
*/
- (NSString*) buildMolecule;
/**
Returns the options dictionary for the molecule the object is currently working on
*/
- (NSMutableDictionary*) buildOptions;
/**
Returns an NSError object describing the error that happend on the
last call to buildPart:options:error:userInfo: if any. If there is
none this method returns nil.
*/
- (NSError*) buildError;
/**
Returns a NSString object containing information on the build
generated by the last call to buildPart:options:error:userInfo: if any. 
If there is none this method returns nil.
*/
- (NSString*) userInfo;
/**
Writes the current structure of the molecule on the
build path to the file at \e path. This structure may
be different to the initial one set due to application of 
preprocessing plugins.
*/
- (void) writeStructureToFile: (NSString*) path;
/**
Cancels the current build, releasing the system currently on the build pathway.
*/
- (void) cancelBuild;
/**
Returns the last completed system if any. If there is none returns nil
*/
- (AdDataSource*) system;
/**
Returns the current build position of the object. i.e. which section
it will build next
\return The current build position (Configuration, TopologyFrame, Merge, Interactions)
*/
- (NSString*) buildPosition;
/**
Removes the current molecule from the builder.
The current build must have been cancelled in order
to remove the molecule. If the build hasnt been cancelled
this method return NO. On success it returns YES
*/
- (BOOL) removeMolecule;
/**
Sets the force field to use. If \e aString is not
in the array returned by availableForceFields (or is nil) this method
does nothing.
*/
- (void) setForceField: (NSString*) aString;
/**
Returns the name of the force field the builder is
currently using
*/
- (NSString*) forceField;
/**
Sets the type of the files the builder is creating
systems from e.g. pdb etc.
\e string must be a valid file name extensions. The valid
file names are returned by knownFileTypes. If \e aString
is not in this array this method does nothing.
*/
- (void) setFileType: (NSString*) aString;
/**
Returns the file name extension identifying the type
of file the builder is currently configured to read
and convert in a system
*/
- (NSString*) fileType;
/**
Returns an array of file extensions representing the type
of files the builder can be configured to read.
*/
- (NSArray*) knownFileTypes;
/**
Returns an array containing the names of the force fields
the builder can be configured to use
*/
- (NSArray*) availableForceFields;
/**
Returns an array containing the name of the
plugins available for preprocessing the current build molecule.
The available plugins depend on the molecules file type.
*/
- (NSArray*) availablePreprocessPlugins;
/**
Returns the options for the currently selected preprocess plugin.
*/
- (NSMutableDictionary*) preprocessOptions;
/**
Loads the preprocess plugin identified by \e aString
*/
- (void) loadPreprocessPlugin: (NSString*) aString;
/**
Applies the currently loaded preprocess plugin 
to the current structure. The structure returned
by the plugin then becomes the structure used for
the build.
If the current structure is nil and/or the current
selected plugin is nil this method does nothing.
*/
- (void) applyPreprocessPlugin: (NSDictionary*) options;
/**
Returns the output string describing the last preprocessing step applied
*/
- (NSString*) preprocessOutputString;
@end

#endif // _ULSYSTEMBUILDER_H_

