package com.actelion.research.chem.io.pdb.parser;

import com.actelion.research.chem.Coordinates;
import com.actelion.research.chem.Molecule;
import com.actelion.research.chem.Molecule3D;

public class ProteinSynthesizer {
	
	private Molecule3D mProtein;
	private int mTerminalC =-1;
	
	/**
	 * an amino acid is added to the protein structure and a peptide coupling is performed, 
	 * if coupling cannot be performed, the function results false and the residue is not added
	 */
	public boolean addResidue(Molecule3D residue) { 
		boolean coupled = false;
		int toDelete = -1;
		int newTerminalN = -1;
		int newTerminalC = -1;
		for(int atom=0;atom<residue.getAtoms();atom++) {
			if(residue.getAtomicNo(atom)==7 && residue.getAtomCustomLabel(atom)==null)
				newTerminalN = atom;
			if(residue.getAtomicNo(atom)==6 && residue.getAtomCustomLabel(atom)==null)
				newTerminalC = atom;
		}
		if(mProtein ==null) { // first residue
			mProtein = residue;
			mTerminalC = newTerminalC;
			coupled = true;
		}
		else if(newTerminalN>-1 && mTerminalC >-1) { //coupling should be performed
			Coordinates coordsC = mProtein.getAtomCoordinates(mTerminalC);
			Coordinates coordsN = residue.getAtomCoordinates(newTerminalN);
			if(coordsC.distanceSquared(coordsN)<Residue.BOND_CUTOFF_SQ) {
				boolean notFound = true;
				for(int i = 0; i< mProtein.getConnAtoms(mTerminalC) && notFound; i++) {
					int a = mProtein.getConnAtom(mTerminalC, i);
					int b = mProtein.getBond(mTerminalC, a);
					if(mProtein.getAtomicNo(a)==8 && mProtein.getBondOrder(b)==1) {
						notFound=false;
						toDelete = mProtein.getConnAtom(mTerminalC, i);
					}
				}
		
				if(toDelete>=0) {
					mProtein.deleteAtom(toDelete);
					int[] atomMap = mProtein.addMolecule(residue);
					mProtein.addBond(mTerminalC, atomMap[newTerminalN], 1);
					mTerminalC = mProtein.getAllAtoms()-(residue.getAllAtoms()-newTerminalC);
					coupled = true;
				}
			}
		}
		mProtein.ensureHelperArrays(Molecule.cHelperNeighbours);
		return coupled;
	}
	
	public Molecule3D getProtein() {
		return mProtein;
	}
}
