#include "../pdb.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>

char* __pdbRecord[] = {
	"ATOM  ",
	"HETATM",
	NULL
} ;

pdbRecordType
pdbRecordTypeAssign(char* s)
{
	pdbRecordType tmp;

	for(tmp=0; tmp!=pdbRecordUnsupported; tmp++) {
		if(0==strncmp(s, __pdbRecord[tmp], RECORDNAME_LEN)) {	
			break;
		}
	}
	return tmp;
}

/*
 * pdbRecordStringAssign
 * 
 */
char* 
pdbRecordStringAssign(pdbRecordType record, char* s)
{
	if(record<pdbRecordUnsupported) {
		sprintf(s, __pdbRecord[record]);
	} else {
		fprintf(stderr, "Not supported record: %d\n", record);
		exit(EXIT_FAILURE);
	}
	return s;
}

/*
 * pdbIsAtom
 *   return value: whether the current record is ATOM/HETATM
 */
int
pdbIsAtom(pdbOneRecord* current) 
{
	if(pdbRecordATOM    == current->record 
	 ||pdbRecordHETATM == current->record) {
		return 1;
	} else {
		return 0;
	}
}

/*
 * pdbZValueGet
 * 	return value: Atomic Mass of the current atom 
 */
int
pdbZValueGet(pdbOneRecord* current)
{
	if(       current->atomName[1] == 'H') {
		return 1;		
	} else if(current->atomName[0] == ' ' && current->atomName[1] == 'C') {
		return 6;		
	} else if(current->atomName[0] == ' ' && current->atomName[1] == 'N') {
		return 7;		
	} else if(current->atomName[0] == ' ' && current->atomName[1] == 'O') {
		return 8;		
	} else if(current->atomName[0] == ' ' && current->atomName[1] == 'P') {
		return 15;	
	} else if(current->atomName[0] == ' ' && current->atomName[1] == 'S') {
		return 16;
	} else if(current->atomName[0] == 'M' && current->atomName[1] == 'G') {
		return 12;
	} else if(current->atomName[0] == 'C' && current->atomName[1] == 'A') {
		return 20;
	} else {
		fprintf(stderr, "Not supported element: %c%c\n", current->atomName[0], current->atomName[1]);
		return 6;
	}
}

/*
 *  pdbAreaInfo
 *  	mean : Averaged position of all atoms	
 *  	max: Distance betweeen averaged position and the farthest atom
 */

void
pdbAreaInfo(pdbFile* pdb, pdbCoord* mean, double* max, int mode)
{
	double tmp;

	pdb->current = pdb->top;
	mean->x = mean->y = mean->z = 0;	
	while(NULL!=pdb->current) {
		if(pdbIsAtom(pdb->current)) {
			mean->x += pdb->current->coord.x;
			mean->y += pdb->current->coord.y;
			mean->z += pdb->current->coord.z;
		}	
		pdb->current = pdb->current->next;
	}

	mean->x /= pdb->nAtom;
	mean->y /= pdb->nAtom;
	mean->z /= pdb->nAtom;


	pdb->current = pdb->top;
	*max = 0;	
	while(NULL!=pdb->current) {
		if(pdbIsAtom(pdb->current)) {
			tmp = sqrt((mean->x - pdb->current->coord.x)*(mean->x - pdb->current->coord.x)
				  +(mean->y - pdb->current->coord.y)*(mean->y - pdb->current->coord.y)
				  +(mean->z - pdb->current->coord.z)*(mean->z - pdb->current->coord.z));
			if(*max<tmp) {
				*max = tmp;
			}
		}	
		pdb->current = pdb->current->next;
	}
}

void pdbTempInfoGet(pdbFile* pdb){
	pdb->tempMin = 1000.0;
	pdb->tempMax = 0.0;
	pdb->current = pdb->top;
	while(NULL!=pdb->current){
		if(pdbIsAtom(pdb->current)){
			//fprintf(stdout,"Temp Factor: %f\n",pdb->current->tempFactor);
			if(pdb->tempMin > pdb->current->tempFactor){
				pdb->tempMin = pdb->current->tempFactor;
			}
			if(pdb->tempMax < pdb->current->tempFactor){
				pdb->tempMax = pdb->current->tempFactor;
			}
		}
		pdb->current = pdb->current->next;
	}
}

void
pdbColorInfoGet(pdbFile* pdb){
	pdb->current = pdb->top;
	while(NULL!=pdb->current){
		if(pdbIsAtom(pdb->current)){
			if(strncmp(pdb->current->atomName," C",2)==0){
				pdb->current->color.R = 0.5;
				pdb->current->color.G = 0.5;
				pdb->current->color.B = 0.5;
			}else if(strncmp(pdb->current->atomName," N",2)==0){
				pdb->current->color.R = 0.0;
				pdb->current->color.G = 0.0;
				pdb->current->color.B = 1.0;
			}else if(strncmp(pdb->current->atomName," O",2)==0){
				pdb->current->color.R = 1.0;
				pdb->current->color.G = 0.0;
				pdb->current->color.B = 0.0;
			}else if(strncmp(pdb->current->atomName," S",2)==0){
				pdb->current->color.R = 0.5;
				pdb->current->color.G = 0.5;
				pdb->current->color.B = 0.0;
			}else if(strncmp(pdb->current->atomName," P",2)==0){
				pdb->current->color.R = 1.0;
				pdb->current->color.G = 0.5;
				pdb->current->color.B = 0.0;
			}else{
				pdb->current->color.R = 0.0;
				pdb->current->color.G = 1.5;
				pdb->current->color.B = 0.0;
			}
		}
		pdb->current = pdb->current->next;
	}
}

void
pdbResColorInfoGet(pdbFile* pdb){
	pdb->current = pdb->top;
	while(NULL!=pdb->current){
		if(pdbIsAtom(pdb->current)){
			if(strcmp(pdb->current->resName,"LYS")==0 ||
			   strcmp(pdb->current->resName,"ARG")==0 ||
			   strcmp(pdb->current->resName,"HIS")==0 ){
				pdb->current->rescolor.R = 0.0;
				pdb->current->rescolor.G = 0.0;
				pdb->current->rescolor.B = 1.0;
			}else if(strcmp(pdb->current->resName,"ASP")==0 ||
					 strcmp(pdb->current->resName,"GLU")==0	){
				pdb->current->rescolor.R = 1.0;
				pdb->current->rescolor.G = 0.0;
				pdb->current->rescolor.B = 0.0;
			}else if(strcmp(pdb->current->resName,"SER")==0 ||
					 strcmp(pdb->current->resName,"THR")==0	){
				pdb->current->rescolor.R = 0.0;
				pdb->current->rescolor.G = 1.0;
				pdb->current->rescolor.B = 0.0;
			}else if(strcmp(pdb->current->resName,"CYS")==0 ||
					 strcmp(pdb->current->resName,"MET")==0 ){
				pdb->current->rescolor.R = 0.5;
				pdb->current->rescolor.G = 0.5;
				pdb->current->rescolor.B = 0.0;
			}else{
				pdb->current->rescolor.R = 0.5;
				pdb->current->rescolor.G = 0.5;
				pdb->current->rescolor.B = 0.5;
			}
		}
		pdb->current = pdb->current->next;
	}
}

void pdbMolecularWeightCalc(pdbFile *pdb){
	pdb->current = pdb->top;
	pdb->MW = 0;
	while(NULL!=pdb->current){
		if(pdbIsAtom(pdb->current)){
			if(strncmp(pdb->current->atomName," C",2)==0){
				pdb->MW += 12.01;
			}else if(strncmp(pdb->current->atomName," N",2)==0){
				pdb->MW += 14.01;
			}else if(strncmp(pdb->current->atomName," O",2)==0){
				pdb->MW += 16.00;
			}else if(strncmp(pdb->current->atomName," S",2)==0){
				pdb->MW += 32.07;
			}else if(strncmp(pdb->current->atomName," P",2)==0){
				pdb->MW += 30.97;
			}else if(strncmp(pdb->current->atomName,"1H",2)==0 ||
					 strncmp(pdb->current->atomName,"2H",2)==0 ||
					 strncmp(pdb->current->atomName,"3H",2)==0 ||
					 strncmp(pdb->current->atomName," H",2)==0 ){
				pdb->MW += 1.003;
			}
		}
		pdb->current = pdb->current->next;
	}
}
