/**
 * @file io_exceptions.h
 * @brief warnings/exceptions occurring in class CIO
 *
 * @author Chuan Li, chuanli@clemson.edu
 *
 * These warnings and exceptions should inherit from the classes CWarning and CException in order to
 * keep track the number of warnings and maintain consistent format.
 */

#ifndef IO_EXCEPTIONS_H_
#define IO_EXCEPTIONS_H_

#include "../interface/exceptions.h"

/**
 * user-specified IO file does not exist
 */
class CUnknownIOFile : public CException
{
   public:
      CUnknownIOFile(const string & strFileName)
      {
         cerr << "ERROR OCCURS WHILE READING IO FILE \"" << strFileName << "\" : FILE DOES NOT EXIST" << endl;
      }
};

/**
 * user-specified SIZ or CRG file does not exist
 */
class CUnknownSizCrgFile : public CException
{
   public:
      CUnknownSizCrgFile(const string & strFileName)
      {
         cerr << "ERROR OCCURS WHILE READING SIZ/CRG FILE \"" << strFileName << "\" : FILE DOES NOT EXIST" << endl;
      }
};

/**
 * user-specified VDW file does not exist.
 * This is for non-polar energy calc. 
 * It contains LJ-sigma/LJ-eps and vdwGamma values for atomtypes
 */
class CUnknownVdWFile : public CException
{
   public:
      CUnknownVdWFile(const string & strFileName)
      {
         cerr << "ERROR OCCURS WHILE READING THE DEFAULT OR USER-SPECIFIED VDW FILE \"" << strFileName << "\" : FILE DOES NOT EXIST" << endl;
         cerr << "              A VALID VDW FILE MUST BE PROVIDED TO OBTAIN NON-POLAR ENERGIES" << endl;
      }
};

/**
 * user-specified PDB/PQR or any structure file does not exist
 */
class CUnknownStructFile : public CException
{
   public:
      CUnknownStructFile(const string & strFileName)
      {
         cerr << "ERROR OCCURS WHILE READING STRUCTURE FILE \"" << strFileName << "\" : FILE DOES NOT EXIST" << endl;
      }
};
/**
 * unknown header in .siz or .crg file
 * Also in newly added .vdw file
 */
class CUnknownForceFileHeader : public CException
{
   public:
      CUnknownForceFileHeader(const string & strFile, const string & strHeader)
      {
         cerr << "UNKNOWN HEADER IN FILE " << strFile << " : " << strHeader << endl;
         cerr << "\t VALID HEADER FOR SIZE FILE IS \'atom__res_radius\' OR \'atom__resnumbc_radius_\'" << endl;
         cerr << "\t VALID HEADER FOR CHARGE FILE IS \'atom__res_radius\' OR \'atom__resnumbc_radius_\'" << endl;
         cerr << "\t VALID HEADER FOR VDW FILE IS \'atom__sigma___epsilon_gamma___\' " << endl;
      }
};

/**
 * unrecognized delphi .pdb file
 */
class CUnknownDelphiPdb : public CException
{
   public:
      CUnknownDelphiPdb(const string & strFile)
      {
         cerr << "THE FILE " << strFile << " IS NOT A DELPHI PDB FILE! " << endl;
         cerr << "\t CHECK THE FILE TYPE! " << endl;           
      }
};

/**
 * unrecognized unformatted .pdb file
 */
class CUnknownUnformattedPdb : public CException
{
   public:
      CUnknownUnformattedPdb(const string & strFile)
      {
         cerr << "ERROR OCCURS WHEN READING THE UNFORMATTED PDB FILE " << strFile << endl;
         cerr << "\t CHECK THE FILE AND TRY AGAIN! " << endl;           
      }
};

/**
 * unrecognized modified .pdb file
 */
class CUnknownModPdb : public CException
{
   public:
      CUnknownModPdb(const string & strFile, const int & iFormatID)
      {
         cerr << "THE FORMAT ID " << iFormatID << " SPECIFIED IN THE MOD PDB FILE " << strFile << " IS NO LONG SUPPORTED." << endl;
         cerr << "\t CURRENT SUPPORTED ID = 1, 4 FOR MOD PDB FILE" << endl;           
      }
};

/**
 * obsolete line in .pdb file
 */
class CUnsupportedCRGDST : public CException
{
   public:
      CUnsupportedCRGDST(const string & strLine)
      {
         cerr << "THE INPUT PDB FILE CONTAINS A LINE \"" << strLine << "\" WITH KEYWORD \"crgdst\" WHICH IS NO LONGER SUPPORTED " << endl;
         cerr << "\t PLEASE UPDATE THE PDB FILE AND TRY AGAIN..." << endl;           
      }
};

/**
 * no object or atom after reading user-specified files
 */
class CNoAtomObjectData : public CException
{
   public:
      CNoAtomObjectData()
      {
         cerr << "# OF ATOMS = 0 AND # OF OBJECTS = 0" << endl;
         cerr << "\t EXITING DUE T NON-EXISTENCE OF ATOM FILE NOR OBJECT DATA" << endl;
      }
};

/**
 * MMPBSA/ TRAJECTORY ANALYSIS
 * mismatch in the number of atoms derived from the trajectory and topology files
 */
class CAtomNumberMismatch : public CException
{
   public:
      CAtomNumberMismatch(const int& natomsTraj , const int& natomsTopol)
      {
         cerr << "MISMATCH IN THE NUMBER OF ATOMS FOUND IN THE TRAJECTORY FILE (" << natomsTraj << ") " ;
         cerr << "AND TOPOLOGY FILE (" << natomsTopol << "). ";
         cerr << "MAKE SURE THAT THE BOTH THE TRAJECTORY AND THE TOPOLOGY CORRESPOND TO EXACTLY THE SAME MOLECULE." << endl;
      }
};

/**
 * MMPBSA/ TRAJECTORY ANALYSIS
 * Number of radius assignments does not match the number of 3D coords read per snapshot.
 */
class CIncompatibleNumberOfRadii : public CException
{
   public:
      CIncompatibleNumberOfRadii(int& numRadii ,int& numAtoms)
      {
          cerr << "NUMBER OF RADIUS VALUES ASSIGNED MASED ON ATOM TYPES IN THE TOPOLOGY (" << numRadii << ") ";
        cerr << "DOES NOT MATCH THE NUMBER OF ATOMS READ IN A SNAPSHOT (" << numAtoms <<")"<< endl;
      }
};

/**
 * MMPBSA/ TRAJECTORY ANALYSIS
 * Incompatible trajectory and topology file types
 * (Not obtained from the same software).
 */
class CBadTrajTop : public CException
{
   public:
      string strTrajType;
      string strTopolType;

      CBadTrajTop(int& iTrajFormatIn, int& iTopolFormatIn)
      {
         switch (iTrajFormatIn)
         {
            case 101:
                strTrajType = "DCD";
                break;
            case 102:
                strTrajType = "XTC";
                break;
            case 103:
                strTrajType = "TRR";
                break;
            case 104:
                strTrajType = "MDCRD";
                break;
            case 105:
                strTrajType = "NETCDF";
                break;
            default:
                strTrajType = "UNKNOWN";
         } //iTrajFormatIn

         switch (iTopolFormatIn)
         {
            case 201:
                strTopolType = "PSF";
                break;
            case 202:
                strTopolType = "TPR";
                break;
            case 203:
                strTopolType = "GRO";
                break;
            case 204:
                strTopolType = "PRMTOP";
                break;
            default:
                strTopolType = "UNKNOWN";
         } //iTopolFormatIn
         
         cerr << "INCOMPATIBLE PAIR OF TRAJECTORY (" << strTrajType << ") AND TOPOLOGY (" << strTopolType << ")." << endl;
      }
};

/*
 * unexpected values found in AMBER's mdcrd file
 */
class CBadMDCRDFile : public CException
{
	public:
	CBadMDCRDFile(const string strMsg)
	{
		cerr << strMsg << endl;
	}
};

/**
 * bad boundaries for the frames to be read from a trajectory 
 * index of the last Frame < index of the first Frame
 */
class CBadFrameBounds : public CException
{
    public:
    CBadFrameBounds(const int& iFrameFirst, const int& iFrameLast)
    {
        cerr << " INDEX OF THE LAST FRAME REQUESTED ("<< iFrameLast << ") CANNOT BE LOWER THAN THE INDEX OF THE FIRST FRAME ("<< iFrameFirst <<")." << endl;
    }
};

/**
 * bad TRR file because the MAGIC number detected in it does not match
 * that which identifies a gromacs TRR file (usually 1995).
 */
class CBadTRR : public CException
{
    public:
    CBadTRR()
    {
        cerr << " BAD TRR INPUT FILE INDICATED BY MAGIC NUMBER MISMATCH. CHECK TO SEE IF GROMACS IS ABLE TO DUMP THIS FILE." << endl;
    }
};

/**
 * no object or atom after reading user-specified files
 */
class CNotReadingObjectFile : public CWarning
{
   public:
      CNotReadingObjectFile()
      {
         cwarn << "YOU ARE NOT READING FROM AN OBJECT FILE!"<<"ASSUMING HAVING ONLY MOLECULES, AND ONE MEDIUM "<<endl;
      }
};

/**
 * no radius record for specified atom
 */
class CUnknownRadius : public CWarning
{
   public:
      CUnknownRadius(const string & strLine)
      {
         cwarn << "NO RADIUS RECORD FOUND FOR \"" << strLine << "\" " << endl;
         //cwarn << "\t PLEASE CHECK THE .siz FILE AND RETRY..." << endl;
      }
};

/**
 * radius of specified heave atom is set to be zero by default
 */
class CZeroHeavyAtomRadius : public CWarning
{
   public:
      CZeroHeavyAtomRadius(const string & strLine)
      {
         cwarn << "RADIUS OF HEAVEY ATOM IN \"" << strLine << "\" IS SET TO ZERO"<< endl;
      }
};

/**
 * charge of specified atom is set to be zero by default
 */
class CUnknownCharge : public CWarning
{
   public:
      CUnknownCharge(const string & strLine)
      {
         cwarn << "NO CHARGE RECORD FOUND FOR \"" << strLine << "\" (CHARGE IS SET = 0)" << endl;
      }
};

/**
 * sigma-gaussian of specified atom is set to be zero by default
 */
class CUnknownSigmaGaussian : public CWarning
{
   public:
      CUnknownSigmaGaussian(const string & strLine, const delphi_real& defaultValue)
      {
         cwarn << "NO SIGMA-GAUSSIAN RECORD FOUND FOR \"" << strLine << "\" (SIGMAG IS SET = " << setprecision (4) << defaultValue << ")" << endl;
      }
};

/**
 * sigma-gaussian (can never be negative or zero) of specified atom is set to be 1.0 by default
 */
class CInvalidSigmaGaussian : public CWarning
{
    public:
       CInvalidSigmaGaussian(const string & strLine)
       {
          cwarn << "NO SIGMA-GAUSSIAN CAN BE NEGATIVE OR ZERO \"" << strLine << "\" (SIGMAG IS SET = 1.0)" << endl;
       }
};

/**
 * non-zero net charge of a residue
 */
class CNonZeroNetCrg : public CWarning
{
   public:
      CNonZeroNetCrg(const string & strResidue, const string & strResidueNum, const delphi_real & fNetCharge)
      {
         cwarn << "\"" << strResidue << strResidueNum << "\" HAS A NET CHARGE OF " << fNetCharge << endl;
      }
};

/**
 * empty atom in .pdb file
 */
class CEmptyAtomsInFile : public CWarning
{
   public:
      CEmptyAtomsInFile(const string & strFile)
      {
         cwarn << "EMPTY ATOMS FOR MIDPOINT DETERMINATION IN FILE "  << strFile << " (ASSUMING ZERO OFFSETS)" << endl;
      }       
};       

/**
 * no LJ or Gamma (non-polar) record for specified atom
 */
class CUnknownLJParam : public CWarning
{
   public:
      CUnknownLJParam (const string & strLine)
      {
         cwarn << "NO LJ/GAMMA RECORD FOUND FOR \"" << strLine << "\" " << endl;
         //cwarn << "\t PLEASE CHECK THE .siz FILE AND RETRY..." << endl;
      }
};

/**
 * using modified .pdb file for sizes and charges as user specifies
 */
class CReadSizeCrgFromPDB : public CWarning
{
   public:
      CReadSizeCrgFromPDB()
      {
         cwarn << "IN PARAMETER FILE, USER SPECIFIES TO READ PDB FILE IN MODIFIED FORMAT "
              << "(CHARGE AND SIZE ARE READ FROM THE PDB FILE AS WELL) \n";
      }
};



#endif // IO_EXCEPTIONS_H_
