/*
   Project: Adun

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

   Author: 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 "AdunKernel/AdunNonBondedTopology.h"

@implementation AdNonBondedTopology

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

DataSource Accessing

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

- (void) _retrieveNonBondedInteractions
{
	NSDebugLLog(@"AdNonBondedTopology", @"Creating nonbonded interaction list.\n");
	
	interactions = [dataSource objectValueForNonbondedInteractions: self];
	interactionDict = [dataSource objectValueForNonbondedInteractionTypes: self];
	//just reading the vdw params at the moment. Later this should be an array
	parameters = [[interactionDict valueForKey:@"TypeOneVDWInteraction"] pointerValue];
	interactionTypes = [[interactionDict keyEnumerator] allObjects];
	coordinates = [[dataSource objectValueForCoordinates: self] pointerValue];

	NSDebugLLog(@"AdNonBondedTopology", @"Complete");
}

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

Initialisation and Maintainence 

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

- (id) initWithEnvironment: (id) object observe: (BOOL) value
{
	if(self = [super initWithEnvironment: object observe: value])
	{
		dataSourceProtocolName = @"AdNonbondedToplogyDataSource";
		dataSourceProtocol = @protocol(AdNonbondedTopologyDataSource);

		listHandler = [AdNonBondedListHandler objectForEnvironment: environment];
		[listHandler retain];

		if(environment != nil)
		{
			[self registerWithEnvironment];
			[self synchroniseWithEnvironment];
		}
	}

	return self;
}

- (id) initWithEnvironment: (id) object
{
	return [self initWithEnvironment: object observe: YES];
}

- (id) init
{
	return [self initWithEnvironment: nil];
}

- (void) _initialisationForListHandler
{
	[listHandler setValue: interactions forKey: @"nonbondedTopology"];	
	[listHandler setValue: [NSValue valueWithPointer: coordinates] forKey: @"coordinates"];
	[listHandler setValue: [NSValue valueWithPointer: parameters] forKey: @"parameters"];	
}

- (void) dealloc
{
	[listHandler release];
	[super dealloc];	
}

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

Protocol Methods implementation

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

/*
 * Environment observation
 */

- (void) updateForKey: (NSString*) key value: (id) value object: (id) object
{
	//no updates as of yet
}

- (void) registerWithEnvironment
{
	//nothing to register
}

- (void) deregisterWithEnvironment
{
	//nothing to deregister
}

- (void) synchroniseWithEnvironment
{
	//nothing to retrieve
}

- (void) setEnvironment: (id) object
{
	[self deregisterWithEnvironment];
	object = environment;
	[self registerWithEnvironment];
}


- (void) reloadData
{
	if(dataSource != nil)
	{
		[self _retrieveNonBondedInteractions];
		[self _initialisationForListHandler];
		[listHandler createList];
		in_p = [[listHandler valueForKey: @"nonbondedInteractions"] pointerValue];
	}
	else
		[NSException raise: NSInternalInconsistencyException
			format: @"No data source has been set (%@)", [self description]];
}

- (void) update
{
	[listHandler update];
	in_p = [[listHandler valueForKey: @"nonbondedInteractions"] pointerValue];
}

- (id) initWithCoder: (NSCoder*) decoder
{
	if([decoder allowsKeyedCoding])
	{
		self = [super initWithCoder: decoder];
		dataSource = [decoder decodeObjectForKey: @"DataSource"];
		listHandler = [[decoder decodeObjectForKey: @"ListHandler"] retain];
	}
	else
		[NSException raise: NSInvalidArgumentException
			format: @"%@ class does not support non keyed coding", [self class]];

	environment = [AdEnvironment globalEnvironment];
	if(environment != nil)
	{
		[self synchroniseWithEnvironment];
		[self registerWithEnvironment];
	}

	//FIXME: Not so sure about this ..
	[self reloadData];
	return self;
}

- (void) encodeWithCoder: (NSCoder*) encoder
{
	if([encoder allowsKeyedCoding])
	{
		[super encodeWithCoder: encoder];
		[encoder encodeObject: listHandler forKey: @"ListHandler"];
		[encoder encodeConditionalObject: dataSource forKey: @"DataSource"];
	}
	else
		[NSException raise: NSInvalidArgumentException
			format: @"%@ class does not support non keyed coding", [self class]];
}

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

Accessors 

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

- (int) numberNonbondedInteractions
{
	return  [listHandler numberNonbondedInteractions];
} 

//The interactions as a linked list

- (NSValue*) nonbondedInteractions
{
	return [NSValue valueWithPointer: in_p];
}

//A dictionary whose keys are various types of nonbonded interaction and whose values are
//the parameters for that interaction for each atom in the system

-(id) nonbondedInteractionTypes
{
	return interactionDict;
}

//The interactions as index sets

- (NSArray*) nonbondedTopology
{
	return interactions;
}

//Dependant setter

- (void) setInteractionLists
{
	[listHandler update];
	in_p = [[listHandler valueForKey: @"nonbondedInteractions"] pointerValue];	
}

@end

