/*
   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/AdunObject.h"

const int AdMatrixSize = sizeof(double);

//constants - First Interaction Types

//! \brief The standard bonded interaction

NSString* const HarmonicBond = @"HarmonicBond";

//! \brief The standard angle interaction

NSString* const HarmonicAngle = @"HarmonicAngle";

//! \brief The standard torsion interaction

NSString* const FourierTorsion = @"FourierTorsions";

//! \brief The standard electrostatic interaction

NSString* const CoulombElectrostatic  = @"CoulombElectrostatic";

//! \brief pure arithmetic vdw interaction (Enzymix, gromos)

NSString* const TypeOneVDWInteraction = @"TypeOneVDWInteraction";

//! \brief geometric plus arithmetic vdw interactions (CHARMM, AMBER)

NSString* const TypeTwoVDWInteraction = @"TypeTwoVDWInteraction";

//nonbonded parameter types

//! \brief Parameters for TypeOneVDWInteraction

NSString* const TypeOneVDWParameters = @"TypeOneVDWParameters";

//! \brief Parameters for TypeTwoVDWInteraction

NSString* const TypeTwoVDWParameters = @"TypeTwoVDWParameters";

//! \brief Partial charges per atom

NSString* const PartialCharges = @"PartialCharges";

@implementation AdObject

//FIXME: change to use methods named _calculate(name)

- (void) updateDependantsOfKey: (NSString*) key
{
	NSEnumerator * myEnumerator;
	NSString* dependantKey;

	//update all the objects that are dependant on key

	myEnumerator = [[dependantsDict valueForKey: key] objectEnumerator];
	while(dependantKey = [myEnumerator nextObject])
		[self setValue: nil forKey: dependantKey];
}

- (void) updateForKey: (NSString*) key value: (id) value object: (id) object
{
	printf("Object %@: Method %@\n", [self description], NSStringFromSelector(_cmd));
	printf("All subclasses must provide their own implmentation of this method\n");
	exit(2);
}

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

Creation

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

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

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

- (id) initWithEnvironment: object observe: (BOOL) value
{
	if(self = [super init])
	{
		environment = object;
		notificationCenter = [NSNotificationCenter defaultCenter];
		observesEnvironment = value;
	}

	return self;
}

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

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

Observation

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

- (void) setObservesEnvironment: (BOOL) value;
{
	if(value == NO && observesEnvironment == YES)
	{
		[self deregisterWithEnvironment];
		observesEnvironment = value;
	}
	else if(value == YES && observesEnvironment == NO)
	{
		observesEnvironment = value;
		[self registerWithEnvironment];
	}
}
	
- (BOOL) observesEnvironment;
{
	return observesEnvironment;
}
- (void) registerWithEnvironment;
{
	[NSException raise: NSInternalInconsistencyException
		format: [NSString stringWithFormat:
		 @"This method is abstract and must be overridden by subclasses",
		 NSStringFromSelector(@selector(_cmd))]];
}


- (void) deregisterWithEnvironment
{
	[NSException raise: NSInternalInconsistencyException
		format: [NSString stringWithFormat:
		 @"This method is abstract and must be overridden by subclasses",
		 NSStringFromSelector(@selector(_cmd))]];
}

- (void) synchroniseWithEnvironment
{
	[NSException raise: NSInternalInconsistencyException
		format: [NSString stringWithFormat:
		 @"This method is abstract and must be overridden by subclasses",
		 NSStringFromSelector(@selector(_cmd))]];
}

- (void) setEnvironment: (id) object
{
	[NSException raise: NSInternalInconsistencyException
		format: [NSString stringWithFormat:
		 @"This method is abstract and must be overridden by subclasses",
		 NSStringFromSelector(@selector(_cmd))]];
}


- (id) initWithCoder: (NSCoder*) decoder
{
	if([decoder allowsKeyedCoding])
	{
		observesEnvironment = [decoder decodeBoolForKey: @"observesEnvironment"];
		notificationCenter = [NSNotificationCenter defaultCenter];
	}
	else
		[NSException raise: NSInvalidArgumentException
			format: @"Object does not support nonkeyed coding"];

	return self;
}

- (void) encodeWithCoder: (NSCoder*) encoder
{
	if([encoder allowsKeyedCoding])
		[encoder encodeBool: observesEnvironment forKey: @"observesEnvironment"];
	else
		[NSException raise: NSInvalidArgumentException
			format: @"Object does not support nonkeyed coding"];
}	

@end
