/* Copyright 2003  Alexander V. Diemand

    This file is part of MolTalk.

    MolTalk 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.

    MolTalk 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 General Public License for more details.

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

/* vim: set filetype=objc: */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "privateResidue.oh"
#include "Residue.oh"
#include "Chain.oh"


static NSMutableDictionary *atomConnectivity = nil;

@implementation Residue (Private)


-(void)setName:(NSString*)p_name	//@nodoc
{
	RETAIN(p_name);
	if (name)
	{
		RELEASE(name);
	}
	name = p_name;
}


-(void)setModName:(NSString*)p_name	//@nodoc
{
	if (p_name)
	{
		RETAIN(p_name);
	}
	if (modname)
	{
		RELEASE(modname);
	}
	modname = p_name;
}


-(void)setModDesc:(NSString*)p_desc	//@nodoc
{
	if (p_desc)
	{
		RETAIN(p_desc);
	}
	if (moddesc)
	{
		RELEASE(moddesc);
	}
	moddesc = p_desc;
}


-(void)setNumber:(NSNumber*)p_number	//@nodoc
{
	RETAIN(p_number);
	if (number)
	{
		RELEASE(number);
	}
	number = p_number;
}


-(void)setSeqNum:(int)p_seqnum		//@nodoc
{
	seqnum = p_seqnum;
}


-(void)setSubcode:(char)p_subcode	//@nodoc
{
	subcode = p_subcode;
}


-(void)setChain:(Chain *)p_chain	//@nodoc
{
	chain = p_chain;
}


-(void)verifyAtomConnectivity	//@nodoc
{
	if (!atomConnectivity)
	{
	/* have to set up the dictionary with the connectivity tables per residue type */
		NSMutableArray *resconn;
		atomConnectivity = RETAIN([NSMutableDictionary new]);
		/* ALA */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",nil]];
		[atomConnectivity setObject:resconn forKey:@"ALA"];
		/* ARG */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD",@"NE",@"CZ",@"NH1",@"NH2",nil]];
		[atomConnectivity setObject:resconn forKey:@"ARG"];
		/* ASN */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"OD1",@"ND2",nil]];
		[atomConnectivity setObject:resconn forKey:@"ASN"];
		/* ASP */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"OD1",@"OD2",nil]];
		[atomConnectivity setObject:resconn forKey:@"ASP"];
		/* CYS */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"SG",nil]];
		[atomConnectivity setObject:resconn forKey:@"CYS"];
		/* GLN */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD",@"OE1",@"NE2",nil]];
		[atomConnectivity setObject:resconn forKey:@"GLN"];
		/* GLU */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD",@"OE1",@"OE2",nil]];
		[atomConnectivity setObject:resconn forKey:@"GLU"];
		/* GLY */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:nil]];
		[atomConnectivity setObject:resconn forKey:@"GLY"];
		/* HIS */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"ND1",@"CD2",@"CE1",@"NE2",nil]];
		[atomConnectivity setObject:resconn forKey:@"HIS"];
		/* ILE */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG1",@"CG2",@"CD1",nil]];
		[atomConnectivity setObject:resconn forKey:@"ILE"];
		/* LEU */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD1",@"CD2",nil]];
		[atomConnectivity setObject:resconn forKey:@"LEU"];
		/* LYS */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD",@"CE",@"NZ",nil]];
		[atomConnectivity setObject:resconn forKey:@"LYS"];
		/* MET */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"SD",@"CE",nil]];
		[atomConnectivity setObject:resconn forKey:@"MET"];
		/* PHE */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD1",@"CD2",@"CE1",@"CE2",@"CZ",nil]];
		[atomConnectivity setObject:resconn forKey:@"PHE"];
		/* PRO */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD",nil]];
		[atomConnectivity setObject:resconn forKey:@"PRO"];
		/* SER */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"OG",nil]];
		[atomConnectivity setObject:resconn forKey:@"SER"];
		/* THR */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"OG1",@"CG2",nil]];
		[atomConnectivity setObject:resconn forKey:@"THR"];
		/* TRP */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD1",@"CD2",@"NE1",@"CE2",@"CE3",@"CZ2",@"CZ3",@"CH2",nil]];
		[atomConnectivity setObject:resconn forKey:@"TRP"];
		/* TYR */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG",@"CD1",@"CD2",@"CE1",@"CE2",@"CZ",@"OH",nil]];
		[atomConnectivity setObject:resconn forKey:@"TYR"];
		/* VAL */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"CB",@"CG1",@"CG2",nil]];
		[atomConnectivity setObject:resconn forKey:@"VAL"];
		/* A */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"O5*",@"C4*",@"O4*",@"C3*",@"C2*",@"C1*",@"N1",@"C2",@"N3",@"C4",@"C5",@"C6",@"N6",@"N7",@"C8",@"N9",nil]];
		[atomConnectivity setObject:resconn forKey:@"  A"];
		/* G */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"O5*",@"C4*",@"O4*",@"C3*",@"C2*",@"C1*",@"N1",@"C2",@"N2",@"N3",@"C4",@"C5",@"C6",@"O6",@"N7",@"C8",@"N9",nil]];
		[atomConnectivity setObject:resconn forKey:@"  G"];
		/* T */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"O5*",@"C4*",@"O4*",@"C3*",@"C2*",@"C1*",@"N1",@"C2",@"O2",@"N3",@"C4",@"O4",@"C5",@"C5M",@"C6",nil]];
		[atomConnectivity setObject:resconn forKey:@"  T"];
		/* C */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"O5*",@"C4*",@"O4*",@"C3*",@"C2*",@"C1*",@"N1",@"C2",@"O2",@"N3",@"C4",@"N4",@"C5",@"C6",nil]];
		[atomConnectivity setObject:resconn forKey:@"  C"];
		/* U */
		resconn = [NSMutableArray new];
		[resconn addObject:[NSArray arrayWithObjects:@"O5*",@"C4*",@"O4*",@"C3*",@"C2*",@"C1*",@"N1",@"C2",@"O2",@"N3",@"C4",@"O4",@"C5",@"C6",nil]];
		[atomConnectivity setObject:resconn forKey:@"  U"];
	}
	
	verified = YES;
	NSArray *connections = [atomConnectivity objectForKey: name];
	if (connections)
	{
		/* test for backbone */
		atomsComplete = YES;
		if (![self getAtomWithName:@"N"])
		{
			atomsComplete = NO;
			return;
		}
		if (![self getAtomWithName:@"CA"])
		{
			atomsComplete = NO;
			return;
		}
		if (![self getAtomWithName:@"C"])
		{
			atomsComplete = NO;
			return;
		}
		if (![self getAtomWithName:@"O"])
		{
			atomsComplete = NO;
			return;
		}
		/* test for sidechain */
		NSArray *connatom;
		NSEnumerator *connenum = [connections objectEnumerator];
		while ((connatom = [connenum nextObject]))
		{
			/* go through all (alternative) namings */
			atomsComplete = YES;
			NSEnumerator *atomenum = [connatom objectEnumerator];
			NSString *atmname;
			while ((atmname = [atomenum nextObject]))
			{
				if ([self getAtomWithName: atmname] == nil)
				{
					atomsComplete = NO;
				}
			}
			if (atomsComplete)
			{
				/* only have to match one of the possible namings */
				return;
			}
		}
		fprintf (stderr,"Residue %s is not complete, missing atoms.\n",[[self description] cString]);
	} else {
		fprintf (stderr,"unknown residue type: %s setting atomsComplete to YES.\n",[name cString]);
		atomsComplete = YES;
	}
}


@end

