/*
   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.
*/

#include "ULSystemBuilder.h"

@implementation ULSystemBuilder


- (void) _buildConfiguration: (NSDictionary*) options
		error: (NSError**) buildError
		userInfo: (NSString**) buildInfo
{
	if([buildPosition isEqual: @"Configuration"])
	{
		configuration = [configurationBuilder buildConfiguration: options
					error: buildError
					userInfo: buildInfo];
		if(configuration == nil)
			[NSException raise: NSInternalInconsistencyException
				format: @"Cannot build configuration - No build molecule has been set"];			
		[configuration retain];
		[buildPosition release];
		buildPosition = [@"TopologyFrame" retain];
	}
	else
	{
		NSWarnLog(@"There is currently a build on the build pathway at position %@.", buildPosition);
		NSWarnLog(@" You must finish or cancel this build before you can call this method");
	}
}

- (void) _buildTopologyFrame: (NSDictionary*) options
		error: (NSError**) buildError
		userInfo: (NSString**) buildInfo
{
	if([buildPosition isEqual: @"TopologyFrame"])
	{
		topologyFrame = [topologyFrameBuilder buildTopologyForSystem:
					[configuration valueForKey: @"Sequences"]
				withOptions: options
				error: buildError
				userInfo: buildInfo];
		[topologyFrame retain];
		[buildPosition release];
		buildPosition = [@"Merge" retain]; 
	}
	else
	{
		NSWarnLog(@"There is currently a build on the build pathway at position %@.", buildPosition);
		NSWarnLog(@" You must finish or cancel this build before you can call this method");
	}
}

- (void) _buildMerge: (NSDictionary*) options
		error: (NSError**) buildError
		userInfo: (NSString**) buildInfo
{
	if([buildPosition isEqual: @"Merge"])
	{
		System = [merger mergeTopologyFrame: topologyFrame 
				withConfiguration: configuration
				error: buildError
				userInfo: buildInfo];
		[System retain];
		[buildPosition release];
		buildPosition = [@"Interactions" retain]; 
	}
	else
	{
		NSWarnLog(@"There is currently a build on the build pathway at position %@.", buildPosition);
		NSWarnLog(@" You must finish or cancel this build before you can call this method");
	}
}

- (void) _buildInteractions: (NSDictionary*) options
		error: (NSError**) buildError
		userInfo: (NSString**) buildInfo
{
	if([buildPosition isEqual: @"Interactions"])
	{
		[interactionsBuilder buildInteractionsForSystem: System
			error: buildError
			userInfo: buildInfo];
		[buildPosition release];
		buildPosition = [@"Complete" retain]; 
	}
	else
	{
		NSWarnLog(@"There is currently a build on the build pathway at position %@.", buildPosition);
		NSWarnLog(@" You must finish or cancel this build before you can call this method");
	}
}

/**************

Public Methods

***************/

- (id) initWithFileType: (NSString*) fileType forceField: (NSString*) forceFieldName
{
	[super init];

	[[NSNotificationCenter defaultCenter]
		 postNotificationName: @"ULSystemBuilderWillBeginInitialisationStepNotification" 
		 object: @"Initialising Configuration Builder"];

	configurationBuilder = [ULConfigurationBuilder builderForFileType: fileType];
	[configuration retain];
	[[NSNotificationCenter defaultCenter]
		 postNotificationName: @"ULSystemBuilderCompletedInitialisationStepNotification" 
		 object: @""];
	[[NSNotificationCenter defaultCenter]
		 postNotificationName: @"ULSystemBuilderWillBeginInitialisationStepNotification" 
		 object: @"Creating Residue Library Document Tree"];
	topologyFrameBuilder = [[ULTopologyFrameBuilder alloc] initWithTopologyLibrary: forceFieldName]; 
	[[NSNotificationCenter defaultCenter]
		 postNotificationName: @"ULSystemBuilderCompletedInitialisationStepNotification" 
		 object: nil];
	[[NSNotificationCenter defaultCenter]
		 postNotificationName: @"ULSystemBuilderWillBeginInitialisationStepNotification" 
		 object: @"Creating Parameter Library Document Tree"];
	merger = [ULMerger new];
	[merger setDelegate: [[ULSimpleMergerDelegate new] autorelease]];
	interactionsBuilder = [[ULInteractionsBuilder alloc] 
					initWithParameterLibrary: forceFieldName];
	[[NSNotificationCenter defaultCenter]
		 postNotificationName: @"ULSystemBuilderCompletedInitialisationStepNotification" 
		 object: @"Complete"];
	buildPosition = [@"Configuration" retain];

	return self;
}

- (void) setBuildMolecule: (NSString*) path
{
	[configurationBuilder setCurrentMolecule: path];
}

- (NSMutableDictionary*) buildOptions
{
	return [configurationBuilder buildOptions];
}

-(void) buildPart: (NSString*) partName 
	options: (NSDictionary*) optionsDict
	error: (NSError**) buildError
	userInfo: (NSString**) buildInfo
{
	if([partName isEqual: @"Configuration"])
	{
		if(System != nil)
		{
			NSWarnLog(@"There is a unclaimed completed build on the pathway!");
			[NSException raise: NSInternalInconsistencyException
				format: @"There is a unclaimed completed build on the pathway!"];
		}

		[self _buildConfiguration: optionsDict
			error: buildError
			userInfo: buildInfo];
	}
	else if([partName isEqual: @"Topology"])
	{
		[self _buildTopologyFrame: optionsDict
			error: buildError
			userInfo: buildInfo];
	}
	else if([partName isEqual: @"Merge"])
	{
		[self _buildMerge: optionsDict
			error: buildError
			userInfo: buildInfo];
	}
	else if([partName isEqual: @"Interactions"])
	{
		[self _buildInteractions: optionsDict
			error: buildError
			userInfo: buildInfo];
	}
}

- (ULSystem*) system
{
	id completedBuild;

	if([buildPosition isEqual: @"Complete"])
	{
		completedBuild = [System autorelease];
		[topologyFrame release];
		[configuration release];
		[buildPosition release];
		buildPosition = [@"Configuration" retain];
		System = nil;
		topologyFrame = nil;
		configuration = nil;
		return completedBuild;
	}
	else
	{
		NSWarnLog(@"There is currently a build on the build pathway at position %@.", buildPosition);
		NSWarnLog(@" You must finish or cancel this build before you can call this method");
		return nil;
	}
}

- (void) cancelBuild
{
	//release everything

	if(![buildPosition isEqual: @"Configuration"])	
	{
		[System release];
		[topologyFrame release];
		[configuration release];
		[buildPosition release];
		System = nil;
		topologyFrame = nil;
		configuration = nil;
		buildPosition = [@"Configuration" retain];
	}
	else
	{
		NSWarnLog(@"There is no build on the pathway");
	}
}

- (BOOL) removeMolecule
{
	if([buildPosition isEqual: @"Configuration"])	
	{
		[configurationBuilder removeCurrentMolecule];
		return YES;
	}
	
	return NO;
}

- (void) setConfigurationBuilder: (id) confBuild
{
	if(configurationBuilder != nil)
		[configurationBuilder release];

	configurationBuilder = confBuild;
	[configurationBuilder retain];
}

- (void) setTopologyFrameBuilder: (id) topBuild
{
	if(topologyFrameBuilder != nil)
		[topologyFrameBuilder release];

	topologyFrameBuilder = topBuild;
	[topologyFrameBuilder retain];
}

- (void) setMerger: (id) merge 
{
	if(merger != nil)
		[merger release];

	merger = merge;
	[topologyFrameBuilder retain];
}

- (NSString*) buildPosition
{
	return buildPosition;
}

@end
