// Chnage History
// 11/5/03 AV Production: Remove deletable flag and use clone info member

#ifndef AT_ERROR_H
#define AT_ERROR_H

#include "at_defs.h"

class SEARCH_DECL AT_Error
{
public :
  virtual ~AT_Error
    ();

  // e.g. "AT_File_Read"
  const AT_String getObjectType
    ()
    const;
  // e.g. "c:\myfile"
  const AT_String getObjectName
    ()
    const;

  // return module name
  const AT_String getModule
    ()
    const;

  // return line num
  uint32 getLineNum
    ()
    const;

  // get the cause of this exception,
  // deleting this exception
  // 0 = at root
  AT_Error *getCause
    ();

  static bool atError();

  // internal structure
  class info;
  friend info;
  
  class SEARCH_DECL Reporter;

protected :
  AT_Error
    (const char *module = 0,
     uint lineNum = 0,
     AT_String objectType = 0,
     AT_String objectName = 0,
     const AT_Error *const prev = 0);

  AT_Error
    (const AT_Error& rhs);

  virtual AT_Error *clone
    ()
    const
  = 0;
  info* GetInfo() const { return i; }

private :
  //const bool deletable;
  info *i;
};

// errors that are not application-specific inherit from this
class SEARCH_DECL AT_General_Error : public AT_Error
{
public :
  class Reporter;
  virtual void report
    (Reporter &reporter)
    const
  = 0;

  static void setReporter(Reporter *reporter);
  static bool retry
    (uint try_num,
     AT_String info);

protected :
  AT_General_Error
    (const char *module = 0,
     uint lineNum = 0,
     AT_String objectType = 0,
     AT_String objectName = 0,
     const AT_Error *const prev = 0) :
    AT_Error(module, lineNum, objectType, objectName, prev)
  {};

  AT_General_Error
    (const AT_General_Error &err) :
    AT_Error(err)
  {};

};

class SEARCH_DECL AT_Logic_Error : public AT_General_Error
{
public :
  AT_Logic_Error
    (const char* module,
     uint lineNum,
     AT_String objectType = 0,
     AT_String objectName = 0);

  #define AT_Logic_Err(T, n)  \
    AT_Logic_Error(__FILE__, __LINE__, (AT_String) typeid(T).name(), (AT_String) (n))

  #ifdef NDEBUG
    #define AT_Assert(pred, T, n)
  #else
    #define AT_Assert(pred, T, n) //{ if (!(pred)) throw AT_Logic_Err(T, n); }
  #endif

  AT_Logic_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;
};

// unimplemented function called
class SEARCH_DECL AT_Function_Error : public AT_General_Error
{
public :
  AT_Function_Error
    (const char* module,
     uint lineNum,
     AT_String objectType,
     AT_String functionName = 0);

  #define AT_Function_Err(T, n)  \
    AT_Function_Error(__FILE__, __LINE__, (AT_String) typeid(T).name(), (AT_String) n)

  AT_Function_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;
};

// e.g. file corrupt
class SEARCH_DECL AT_Corrupt_Error : public AT_General_Error
{
public :
  AT_Corrupt_Error
    (const char* module,
     uint lineNum,
     AT_String objectType,
     AT_String objectName = 0,
     uint32 badValue = 0);

  #define AT_Corrupt_Err(T, n)  \
    AT_Corrupt_Error(__FILE__, __LINE__, (AT_String) typeid(T).name(), (AT_String) n)

  AT_Corrupt_Error *clone
    ()
    const;

  uint32 getBadValue
    ()
    const;

  virtual void report
    (Reporter& r)
    const;

private :
  const uint32 bad_value;
};

// bad value passed
class SEARCH_DECL AT_Bounds_Error : public AT_General_Error
{
public :
  AT_Bounds_Error
    (const char* module,
     uint lineNum,
     AT_String objectType,
     AT_String objectName = 0,
     uint32 badValue = 0);

  #define AT_Bounds_Err(T, n, val)  
  /*\
    AT_Bounds_Error(__FILE__, __LINE__, (AT_String) typeid(T).name(), (AT_String) n, val)
  */

  AT_Bounds_Error *clone
    ()
    const;

  uint32 getBadValue
    ()
    const;

  virtual void report
    (Reporter& r)
    const;

private :
  const uint32 bad_value;
};

class SEARCH_DECL AT_System_Error : public AT_Error
{
public :
  AT_System_Error
    (const char* module,
     uint lineNum);

  #define AT_System_Err  \
    AT_System_Error(__FILE__, __LINE__)

  AT_System_Error *clone
    ()
    const;
  uint32 getErrorNum
    ()
    const;

  virtual void report
    (Reporter& r)
    const;

private :
  const uint32 error_num;
};

class SEARCH_DECL AT_File_Open_Error : public AT_General_Error
{
public :
  AT_File_Open_Error
    (const char* module,
     uint lineNum,
     AT_String objectType = 0,
     AT_String objectName = 0);

  #define AT_File_Open_Err(T, n)  \
    AT_File_Open_Error(__FILE__, __LINE__, (AT_String) typeid(T).name(), (n))

  AT_File_Open_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;
};

class SEARCH_DECL AT_File_Type_Error : public AT_General_Error
{
public :
  AT_File_Type_Error
    (const char* module,
     uint lineNum,
     uint expected,
     uint actual,
     AT_String objectType = 0,
     AT_String objectName = 0);

  #define AT_File_Type_Err(T, n, exp, act)  \
    AT_File_Type_Error(__FILE__, __LINE__, exp, act, (AT_String) typeid(T).name(), (n))

  AT_File_Type_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;

private :
  const uint expected;
  const uint actual;
};

class SEARCH_DECL AT_File_Read_Error : public AT_General_Error
{
public :
  AT_File_Read_Error
    (const char* module,
     uint lineNum,
     AT_String objectType = 0,
     AT_String objectName = 0);

  #define AT_File_Read_Err(T, n)  \
    AT_File_Read_Error(__FILE__, __LINE__, (AT_String) typeid(T).name(), (n))

  AT_File_Read_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;
};

class SEARCH_DECL AT_File_Write_Error : public AT_General_Error
{
public :
  AT_File_Write_Error
    (const char* module,
     uint lineNum,
     AT_String objectType = 0,
     AT_String objectName = 0);

  #define AT_File_Write_Err(T, n)  \
    AT_File_Write_Error(__FILE__, __LINE__, (AT_String) typeid(T).name(), (n))

  AT_File_Write_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;
};

class SEARCH_DECL AT_Constructor_Error : public AT_General_Error
{
public :
  AT_Constructor_Error
    (const char* module,
     uint lineNum,
     AT_String objectType,
     const AT_Error *const prev = 0);

  #define AT_Constructor_Err(prev)  \
    AT_Constructor_Error(__FILE__, __LINE__, (AT_String) typeid(*this).name(), prev)

  AT_Constructor_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;
};

class SEARCH_DECL AT_Unexpected_Error : public AT_General_Error
{
public :
  AT_Unexpected_Error
    (const char* module,
     uint lineNum);

  #define AT_Unexpected_Err  \
    AT_Unexpected_Error(__FILE__, __LINE__)

  AT_Unexpected_Error *clone
    ()
    const;

  virtual void report
    (Reporter& r)
    const;
};

#endif
