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

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

			     list_exposed_polar.c

Purpose:
	List all polar residues exposed at the surface. As each residue
	will (generally) occur more than once in docking matrix,  it is
	necessary to remove  the redundant data  to minimize the number
	of symbols which should be drawn.  This function ignores apolar
	residues as they are not involved in hydrogen bonds.

Input:
	(1) Pointer to RuntimeS structure.
	(2) The complex index (1 = bottom, 2 = top).

Output:
	(1) The list of exposed polar residues will be prepared.
	(2) Return value.

Return value:
	(1) Positive on success.
	(2) Negative on failure.

Notes:
	(1) The number of exposed polar residues should be reset at the
	    beginning of this function.

	(2) Indentation is exceptionally 4 spaces.

========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:=================================================*/

void		ErrorMessage_ (char *, char *, char *,
			       char *, char *, char *, char *);
int		IsPolar_ (char *);

/*======list exposed polar residues:=========================================*/

int ListExposedPolarResidues_ (RuntimeS *runtimeSP, int docking_complexI)
{
MolComplexS		*curr_mol_complexSP;
int			*exposed_atomIP;
ExposedResidueS		*exposed_polarSP;
int			exposed_polarN = 0;
int			matrix_width;
int			rowI, columnI, combinedI;
int			*curr_cellP;
int			atomI;
AtomS			*curr_atomSP;
char			pure_residue_nameA[RESNAMESIZE];
char			chainID;
int			residue_sequenceI;
char			residue_insertion_code;
int			residue_foundF;
int			exposed_polarI;
ExposedResidueS		*curr_exposedSP;
int			int_return_value;

/* Check the complex index and prepare the pointers: */
if (docking_complexI == 1)
    {
    curr_mol_complexSP = runtimeSP->mol_complex1SP;
    exposed_atomIP = runtimeSP->exposed_atom1IP;
    exposed_polarSP = runtimeSP->exposed_polar1SP;
    runtimeSP->exposed_polar1N = 0;
    }
else if (docking_complexI == 2)
    {
    curr_mol_complexSP = runtimeSP->mol_complex2SP;
    exposed_atomIP = runtimeSP->exposed_atom2IP;
    exposed_polarSP = runtimeSP->exposed_polar2SP;
    runtimeSP->exposed_polar2N = 0;
    }
else
    {
    ErrorMessage_ ("garlic", "ListExposedResidues_", "",
		   "Bad macromolecular complex index!\n",
		   "", "", "");
    return -1;
    }

/* Prepare the matrix width: */
matrix_width = runtimeSP->docking_matrix_width;

/* Scan docking matrix: */
for (rowI = 0; rowI < matrix_width; rowI++)
    {
    for (columnI = 0; columnI < matrix_width; columnI++)
	{
	/* Prepare the combined index (the actual array index): */
	combinedI = rowI * matrix_width + columnI;

	/* Prepare the pointer to the current cell (matrix element): */
	curr_cellP = exposed_atomIP + combinedI;

	/* Prepare and check the atomic index: */
	atomI = *curr_cellP;
	if (atomI < 0) continue;

	/* Check is that atom present at all in the current complex: */
	if (atomI >= (int) curr_mol_complexSP->atomsN) continue;

	/* Pointer to the current atom: */
	curr_atomSP = curr_mol_complexSP->atomSP + atomI;

	/* Copy the residue data associated with the current cell: */
	strcpy (pure_residue_nameA, curr_atomSP->raw_atomS.pure_residue_nameA);
	chainID = curr_atomSP->raw_atomS.chainID;
	residue_sequenceI = curr_atomSP->raw_atomS.residue_sequenceI;
	residue_insertion_code = curr_atomSP->raw_atomS.residue_insertion_code;

	/* Scan the list of  exposed polar residues; */
	/* the current residue may be there already: */
	residue_foundF = 0;
	for (exposed_polarI = 0;
	     exposed_polarI < exposed_polarN;
	     exposed_polarI++)
	    {
	    /* Pointer to the current exposed polar residue: */
	    curr_exposedSP = exposed_polarSP + exposed_polarI;

	    if (curr_exposedSP->residue_sequenceI !=
		residue_sequenceI) continue;

	    /* Compare chain identifiers: */
	    if (curr_exposedSP->chainID != chainID) continue;

	    /* Compare residue names: */
	    if (strcmp (curr_exposedSP->pure_residue_nameA,
			pure_residue_nameA) != 0) continue;

	    /* Compare residue insertion codes: */
	    if (curr_exposedSP->residue_insertion_code !=
		residue_insertion_code) continue;

	    /* If this point is reached, residue is found: */
	    residue_foundF = 1;
	    break;
	    }

	/* If residue was found before, check the next cell: */
	if (residue_foundF) continue;

	/* If  this point  is reached,  the residue  associated with */
	/* the current cell was not found before. Check is it polar: */
	if ((int_return_value = IsPolar_ (pure_residue_nameA)) < 0) continue;

	/* Well, if this point is reached, residue is polar and found */
	/* for the first time in docking matrix.  Add it to the list: */
	curr_exposedSP = exposed_polarSP + exposed_polarN;
	strcpy (curr_exposedSP->pure_residue_nameA, pure_residue_nameA);
	curr_exposedSP->chainID = chainID;
	curr_exposedSP->residue_sequenceI = residue_sequenceI;
	curr_exposedSP->residue_insertion_code = residue_insertion_code;

	/* Initialize donorI: */
	curr_exposedSP->donorI = int_return_value;

	/* Store the atomic index as  the representative */
	/* index.  This is a temporary setting; the true */
	/* representative atom will be identified later. */
	curr_exposedSP->representative_atomI = atomI;

	/* Increase the counter: */
	exposed_polarN++;
	}
    }

/* Store the number of exposed residues: */
if (docking_complexI == 1) runtimeSP->exposed_polar1N = exposed_polarN;
else runtimeSP->exposed_polar2N = exposed_polarN;

/* Return positive value on success: */
return 1;
}

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


