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

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

				disulfide_bonds.c

Purpose:
	Prepare disulfide bonds.  Only the distance  between two sulfur
	atoms is checked; the angle between two methylene groups is not
	checked.

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

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

Return value:
	(1) The total number of bonds on success.
	(2) Zero if there are no atoms.
	(3) Negative, if there are some atoms but there are no bonds.

Notes:
	(1) If some atoms are deleted or inserted, all bonds have to be
	    updated. Note that array indices are shifted after addition
	    or deletion of atoms;  that's the most important reason for
	    thorough revision of bonds.

========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		CheckDistance_ (double *, AtomS *, AtomS *, ConfigS *);
int		AddBond_ (AtomS *, int, int, int, size_t, double, int);

/*======prepare disulfide bonds:=============================================*/

size_t DisulfideBonds_ (MolComplexS *mol_complexSP,
			int mol_complexI, ConfigS *configSP)
{
size_t		total_bondsN = 0;
int		styleI;
size_t		atomsN, atom1I, atom2I;
		/* Use signed int to store the following indices: */
AtomS		*atom1SP, *atom2SP;
int		pairID;
int		bond_typeI;
double		distance;
char		alt_location1, alt_location2; 

/* Initialize the styleI: */
styleI = 1;

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

/* Disulfide bonds are treated as type 2: */
bond_typeI = 2;

/* The outer atomic loop: */
for (atom1I = 0; atom1I < atomsN; atom1I++)
	{
	/* Pointer to atom 1: */
	atom1SP = mol_complexSP->atomSP + atom1I;

	/* Check is this sulfur: */
	if (strcmp (atom1SP->raw_atomS.chemical_symbolA, " S") != 0) continue;

	/* The inner atomic loop: */
	for (atom2I = 0; atom2I < atomsN; atom2I++)
		{
		/* Atom is not bound to itself: */
		if (atom2I == atom1I) continue;

		/* Pointer to atom 2: */
		atom2SP = mol_complexSP->atomSP + atom2I;

		/* Both atoms should be sulfur atoms: */
		if (strcmp (atom1SP->raw_atomS.chemical_symbolA, " S") != 0)
			continue;
		if (strcmp (atom2SP->raw_atomS.chemical_symbolA, " S") != 0)
			continue;

		/* Check is there a chemical bond: */
		pairID = CheckDistance_ (&distance,
					 atom1SP, atom2SP, configSP);

		/* If bond is bad, check the next atom 2: */
		if (pairID <= 0) continue;

		/* Compare the alternate location indicators; */
		/* if both indicators  are different from ' ' */
		/* and mutually different,  the bond  is bad! */
		alt_location1 = atom1SP->raw_atomS.alt_location;
		alt_location2 = atom2SP->raw_atomS.alt_location;
		if ((alt_location1 != alt_location2) &&
		    (alt_location1 != ' ') && (alt_location2 != ' '))
			{
			continue;
			}

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

		/* Add bond to atom 1: */
		AddBond_ (atom1SP,
			  pairID, bond_typeI,
			  mol_complexI, atom2I,
			  distance, styleI);

		/* Update the number of bonds in a macromolecular complex: */
		total_bondsN++;
		}
	}

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

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


