#ifndef  __Strand_H
#define __Strand_H

#include "Vector3.h"
#include "Molecule.h"
#include "Particle.h"
#include "Atom.h"
#include <iostream>
#include "StrandPDB.h"
#include <utility>

using std::pair;

/*
CLASS 
  StrandConnection

  This class defines the connection between two strands in the same beta 
  sheet.

KEWORDS
  strand, connection, sheet, nytrogen group, hydrogen bonding

AUTHORS
  Zipi Fligelamn (zipo@math.tau.ac.il)

  Copyright: SAMBA group, Tel-Aviv Univ. Israel, 1999.

CHANGES LOG
<UL>
<LI>
</UL>

GOALS
  Since class defines the connection between two strands in the same beta 
  sheet. The connection is defined from strand n to strand n-1 in the sheet.
  Thus the first defined strand cannot have a connection information, thus
  it defines an empty StrandConnection. 
  The connection is specified by one hydrogen bond between each such pair 
  of strand. This is done by providing thew hydrogen bonding between the 
  current and the previous strands.
USAGE
  to be used only in the context of a full sheet
*/
class StrandConnection {
public:
  typedef pair< char,int> ConnectEnd;
  
  // GROUP: Constructors 

  //// Empty Constructor
  StrandConnection();
  
  //// Regular Constructor holding all the appropriate infromation
  StrandConnection(const char curAtomId, const int curResSeq,
                   const char prevAtomId, const int prevResSeq);
  
  //// Copy constructor
  StrandConnection(const StrandConnection& stcn);
  
  //// Constructor from the appropriate PDB Line
  explicit StrandConnection(const char* const PDBrec);
   
  // GROUP : Geometric information
  
  //// Given an appropriate Molecules that was read from the same pdb file
  // will return a normed vector of the connection direction.
  // The direction is always defined from the previous strand to
  // the current strand
  Vector3 connectionDirection(const Molecule< Particle>& mol) const;

  
  // GROUP: Data members information
  
  //// the atom number and chain defining the connection on the current
  // strand in the sheet
  inline ConnectEnd currEnd() const;
  
  //// the atom number and chain defining the connection on the previous
  // strand in the sheet
  inline ConnectEnd prevEnd() const;
 
  // GROUP: Boolean Operation
  
  //// Equality operator 
  bool operator==(const StrandConnection& stcn);
  
  //// An indication that this connection was started from a first strand
  // in the sheet PDB record
  bool isEmpty() const;

  //// Ostream operator for various  puproses notice the atoms apper in the 
    // following way (type of atom , RESIDUE number) there is no atom number
    // only the residue number this atom belongs to.
  friend ostream& operator<<(ostream& s, const StrandConnection& stcn);
  private:
  ConnectEnd curr,prev;
};

/*
CLASS 
  Strand
  
  This class defines strand that is a part of the beta sheet.

KEWORDS
  beta, starnd, parallelism, connection, nytrogen group, hhydrogen bonding

AUTHORS
  Zipi Fligelamn (zipo@math.tau.ac.il)

  Copyright: SAMBA group, Tel-Aviv Univ. Israel, 1999.

GOALS
USAGE
*/
class Strand {
public:
  typedef StrandPDB::RelativeParallelism  RelativeParallelism;

  // GROUP : Constructors

  //// The empty constructor default values are given
  Strand();

  //// A regular constructor with  all infromation constructor all 
  // infromation has a deafult value
  Strand(short StrandNum,
	 short sseNum,
	 int initResidueNum,
	 int endResidueNum, 
         char initChainID,
	 char endChainID,
	 RelativeParallelism sense, 
         const StrandConnection& stcn);
  
  //// The constrcutor stright from the pdb records.
  explicit Strand(const char* const PDBrec);
    
    //// Copy constructor
    Strand(const Strand& st);
    
    
    // GROUP:  Data members information
    
    //// The number of the strand insied the  beta sheet
    inline short strandNumber() const;

    unsigned short sseIdNum() const{
	return sseNum;
    }

    
    //// The residue number that begins this particular strand.
    //  Please Notice! that this residue is relative to the chain 
    // if you read the atoms through the Atom class you might find
    // that residue 32 in chain B has a different numbering there
    inline int startResidue() const;
    
    //// The residue number that ends this particular strand.
  //  Please Notice! that this residue is relative to the chain 
    // if you read the atoms through the Atom class you might find
    // that residue 32 in chain B has a different numbering there
    inline int endResidue() const;
    
  inline int size() const;

    //// The chain where the strand begins, if there are no chain a '?' will
    // be returned
    inline char initChainID() const;
  
    //// The chain where the strand ends, if there are no chain a '?' will
    // be returned
    inline char endChainID() const;
    
    //// The type of parallelism this strand holds rlatively to the 
    // previous strand in the sheet
    inline RelativeParallelism typeParallel() const;
    
    //// the connection information to the previous strand
    // if this is the first strand the emopty connection will be returned.
    inline StrandConnection stConnection() const;
    
    //// Checking whether this strand is the first strand in the sheet
    inline bool isFirstStrand() const;
    
    //// Checking if residue number X is in Strand
    inline  bool isResInStrand(const int resNum) const;
    
    //// Checking if a certain atom is in Strand 
    bool isAtomInStrand(const Atom& at) const;

  //// An output stream in the follwoing format
  // STRAND num:<num in sheet>
  // begin: (<residue number> , [<chain name>]) end: (<residue number> , [<chain name>])
  // Type: <Type of Connection to the previous strand if exists>
  // from atom (<n or O>, <Atom's Residue num>)  to atom ((<n or O>, <Atom's Residue num>)
  // LAST LINE: is detailed information on the connection
  friend ostream& operator<<(ostream& s, const Strand& str);

private:
  short strandNum;
  unsigned short sseNum;
  int initResNum, endResNum;
  char initChainId, endChainId;
  RelativeParallelism pr;
  // will be emtpy if first strand in the sheet
  StrandConnection cnt;
};

/**************************
  Inline Defintions
  ************************/

StrandConnection::ConnectEnd StrandConnection::currEnd() const
{
  return curr;
}

StrandConnection::ConnectEnd StrandConnection::prevEnd() const
{
  return prev;
}

short Strand::strandNumber() const
{
  return strandNum;
}

int Strand::startResidue() const
{
  return initResNum;
}

int Strand::endResidue() const
{
  return endResNum;
}

int Strand::size() const
{
  return endResNum - initResNum + 1;
}

char Strand::initChainID() const
{
  return initChainId;
}

char Strand::endChainID() const
{
  return endChainId;
}

Strand::RelativeParallelism Strand::typeParallel() const
{
  return pr;
}

StrandConnection Strand::stConnection() const
{
  return cnt;
}

bool Strand::isFirstStrand() const
{
  return cnt.isEmpty();
}

bool Strand::isResInStrand(const int resNum) const
{
    return ((resNum >= initResNum) && (resNum <= endResNum));
}

#endif


