/* Copyright (C) 2001-2003 Damir Zucic */

/*=============================================================================

				pseudo_bonds.c

Purpose:
	Prepare pseudo-bonds. Pseudo bonds are formed between neighboring
	Q atoms.  In garlic,  there are  two pseudoelements,  jellium and
	quarkonium (J and Q).  These  imaginary elements are used to draw
	polygonal lines and inert atoms.  J atoms  do not form any bonds,
	while Q atoms bind to  neighboring Q atoms or, more precisely, to
	the atoms which are listed as  the nearest neighbors in PDB file.
	The actual distance between neighboring Q atoms is not important.

Input:
	(1) Pointer to MolComplexS structure.
	(2) The array index of a given macromolecular complex.
	(3) Pointer to ConfigS structure.

Output:
	(1) Information about pseudo-bonds added.
	(2) Return value.

Return value:
	(1) The total number of pseudo-bonds on success.
	(2) Zero if there are no pseudo-atoms.

Notes:
	(1) Pseudo-bonds are treated as type 11.

	(2) Pair identifier and bond length are not important for pseudo-
	    bonds. Both values are set to zero.
	    

========includes:============================================================*/

#include <stdio.h>

#include <string.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/

int		AddBond_ (AtomS *, int, int, int, size_t, double, int);

/*======prepare pseudo-bonds:================================================*/

size_t PseudoBonds_ (MolComplexS *mol_complexSP,
		     int mol_complexI, ConfigS *configSP)
{
size_t		pseudo_bondsN = 0;
size_t		atomsN, atomI;
		/* Use signed int to store the following indices: */
int		neigh_start, neigh_end, neighborI, combinedI;
size_t		neighbor_arrayI;
AtomS		*curr_atomSP, *curr_neighborSP;
char		*symbolP;
int		serial1I, serial2I;
char		chain1ID, chain2ID;

/* Return zero if there are no atoms: */
atomsN = mol_complexSP->atomsN;
if (atomsN == 0) return 0;

/* The first and the last neighbor to be checked: */
neigh_start = -1;     /* Note the sign! */
neigh_end   =  1;

/* Scan all atoms: */
for (atomI = 0; atomI < atomsN; atomI++)
	{
	/** Pointer to the current atom: **/
	curr_atomSP = mol_complexSP->atomSP + atomI;

	/** Only Q atoms form pseudo-bonds: **/
	symbolP = curr_atomSP->raw_atomS.chemical_symbolA;
	if (strcmp (symbolP, " Q") != 0) continue;

	/** If this point is reached, initialize the number of bonds: **/
	curr_atomSP->bondsN = 0;

	/** Copy the atomic serial number: **/
	serial1I = curr_atomSP->raw_atomS.serialI;

	/** Copy the chain idenfier: **/
	chain1ID = curr_atomSP->raw_atomS.chainID;

	/** Scan the neighborhood of a given atom: **/
	for (neighborI = neigh_start; neighborI <= neigh_end; neighborI++)
		{
		/** Atom is not chemically bound to itself: **/
		if (neighborI == 0) continue;

		/** Prepare and check the combined index: **/
		combinedI = atomI + neighborI;
		if (combinedI < 0) continue;
		if (combinedI >= (int) atomsN) break;

		/** If combined index is good, use it as array index: **/
		neighbor_arrayI = combinedI;

		/** Pointer to the current neighbor: **/
		curr_neighborSP = mol_complexSP->atomSP + neighbor_arrayI;

		/** Copy the atomic serial number: **/
		serial2I = curr_neighborSP->raw_atomS.serialI;

		/** Copy the chain idenfier: **/
		chain2ID = curr_neighborSP->raw_atomS.chainID;

		/** Compare atomic serial numbers: **/
		if ((serial1I + 1 != serial2I) &&
		    (serial1I != serial2I + 1))
			{
			continue;
			}

		/** Compare chain identifiers: **/
		if (chain1ID != chain2ID) continue;

		/** If this point is reached, the bond does exist! **/

		/** Add bond to the current atom. Use dummy values **/
		/** for pairID and bond length (set both to zero). **/
		/** Pseudo bonds  are treated as bonds of type 11. **/
		AddBond_ (curr_atomSP,
			  0, 11,
			  mol_complexI, neighbor_arrayI,
			  0.0, configSP->default_bond_styleI);

		/* Update the number of pseudo bonds: **/
		pseudo_bondsN++;
		}
	}

/* If this point is reached, return the total number of pseudo bonds: */
return pseudo_bondsN;
}

/*===========================================================================*/


