#ifndef __Helix_H
#define __Helix_H



#include <iostream>
#include <fstream>
#include <vector>
#include <utility>

#include "HelixPDB.h"
#include "Vector3.h"
//#include "Particle.h"
//#include "Molecule.h"
#include "Atom.h"


/*
CLASS
  Helix
  
  This class defines the information on the secondary structure alpha helix.
  

KEYWORDS
  PDB, protein, helix, right-handed, left-handed, record, atom, residue, 
  structure, coordinate, field

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

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

CHANGES LOG
<UL>
<LI> 02.05.02 - Oranit Shem-Tov (ornit@math.tau.ac.il):
     - Fixing a small bug in the constructor that gets a PDB line as
     an input. The bug was with the length field of. It appears that
     this field is not always contains the length of the helix. For
     example, take a look at the 1ANT PDB FILE.  
</Ul> 

GOALS
  This class allows you to check and read the alpha helix lines in 
  a PDB file or read an information on the helix on its on grounds

USAGE
  This class can be used with any relations that need the knowledge of
  the secondary structure in a molecule. It can be used to define a selector
  that will work with any kind of selectors (like selecting all the 
  atoms that belong to the alpha helix
*/
class Helix
{
public:
  typedef HelixPDB::HelixType HelixType;
  
  // GROUP: Constructors

  //// Both the empty constructor and the regular constructor that hold 
  // all the infromation.
  Helix(const short helixNum = 0,
	const short sseNum = 0,
        const int begResidue=-1, const int endResidue=-1,
        const char beginChn='?', const char endChn='?', 
        const unsigned short lenHelix=0,
        const HelixType htype = HelixPDB::Unknown);
  
  //// A constructor utilizing all the methods in the HelixPDB
  // to read the appropriate information from the helix record in the 
  // PDB. 
  explicit Helix(const char* const pdbRec);
  
    //// Copy Constructor
    Helix(const Helix& h);
    
    // GROUP: Data members information
  
    //// The helix number in the molecule
  inline unsigned short helixIdNum() const;

    //// The SSE number in the molecule
  inline unsigned short sseIdNum() const;
  
  //// The number of the start residue of the helix. The number is relative to
  // the chain  if you read the atoms through the Atom class you might find
  // that residue num 25 in chain B has a different numbering there
  inline int startResidue() const;
  
  //// The number of the end residue of the helix. The number is relative to
  // the chain  if you read the atoms through the Atom class you might find
  // that residue num 25 in chain B has a different numbering there
  inline int endResidue() const;

  //// The chain char Id where the helix starts. '?' will be returned 
  // if there is no chain in this molecule
  inline char startChain() const;
  
  //// The chain char Id where the helix ends. '?' will be returned 
  // if there is no chain in this molecule
  inline char end_Chain() const;
  
  //// The length of the helix
  inline unsigned short helixLength() const;
  
  //// The type of the helix if it known, the different types can be found 
  // in HelixPDB
  inline HelixType      helixType() const;

  //// checking if a residue number is in Helix no checking on chain
  inline bool isResidueInHelix(const int resNum) const;
  //// checking if an Atom is in Helix with chain verification
  bool isAtomInHelix(const Atom& at) const;
    
  //// ostream operator allowing to print all the infromation
  // in a special format:
  // HELIX <helix num>
  //strat: (<residue number> , [<chain name>])
  //end  : (<residue number> , [<chain name>])
  // length = <length of the helix>      Type = <the type according to the 
  //                                             defintions in the PDB contents
  //                                             manual>
  friend ostream& operator<<(ostream& s, const Helix& hel);

private:
  // data members 
  unsigned short idNum;   // The Helix number in the molecule
  unsigned short sseNum;
  int beginRes;
  int endRes;
  char beginChain;
  // for case when the Helix is cross chain
  char endChain;
  unsigned short len; 
  HelixType type;
};

/**********************
  Inline functions
  ********************/
unsigned short Helix::helixIdNum() const
{
  return idNum;
}


unsigned short Helix::sseIdNum() const
{
  return sseNum;
}


int Helix::startResidue() const
{
  return beginRes;
}

int Helix::endResidue() const
{
  return endRes;
}

char Helix::startChain() const
{
  return beginChain;
}

char Helix::end_Chain() const
{
  return endChain;
}

unsigned short Helix::helixLength() const
{
  return len;
}

Helix::HelixType Helix::helixType() const
{
  return type;
}

bool Helix::isResidueInHelix(const int resNum) const
{
    return (resNum >= beginRes && resNum <= endRes);
}
#endif 



