///////////////////////////////////////////////////////////////////////////////
// DRT ExceptionServices
//Obsolete really but maintained for old DRT code.
///////////////////////////////////////////////////////////////////////////////

#include "drs/drs_exc.h"
#include "base/at_error.h"
#include <windows.h>

#define ExceptionSpace (iExceptionCount < (sizeof(sExceptions)/sizeof(T_ExceptionString)))

void AT_ExceptionList::ExceptionsUnwind( AT_Error &exception)
{
  iExceptionCount = 0;
  iExceptionCur = 0;

  //ExceptionReport x_rpt;
  //Need to check type exception: special = AT_Index::noIndex & AT_Index::openError
  for (AT_Error *e = &exception; e; e = e->getCause())
    {
    AT_Index_List::Error *err = dynamic_cast<AT_Index_List::Error *>(e);
    if (err)
      {
      IndexErrorReporter rpter(this);
      err->report(rpter);
      }
    else
      {
      AT_General_Error *err = dynamic_cast<AT_General_Error*>(e);
      if (err)
        {
        ErrorReporter rpter(this);
        err->report(rpter);
        }
      }
    }
}

uint16 AT_ExceptionList::ExceptionCount()
{
  return( iExceptionCount);
}

int16 AT_ExceptionList::ExceptionLen()
{
  if( !iExceptionCount) return( -1);

  return( (int16) strlen((const char*) sExceptions[iExceptionCur]));
}

void AT_ExceptionList::ExceptionPop( byte *sDest, uint16 iDestLen)
{
  if( iDestLen && sDest) *sDest = 0;
  if( !iExceptionCount || iExceptionCur >= iExceptionCount) return;

  strncpy( (char*) sDest, (const char*) sExceptions[iExceptionCur++], iDestLen);
  sDest[iDestLen-1] = 0; // Null-term
}

void AT_ExceptionList::ExceptionPush( byte *sSrc)
{
  if( ExceptionSpace)
    strcpy((char *)sExceptions[iExceptionCount++], (const char*) sSrc);
}

/////////////////////////////////////////////////////////////////////////////////
// Exception Reports :: AT_Error
/////////////////////////////////////////////////////////////////////////////////
void ErrorReporter::report(const AT_Error *const err)
{
  T_ExceptionString s;

  wsprintfA( (char *) s,
       "Internal error: module %s, line %lu, object %s, type = %s",
       err->getModule(), err->getLineNum(), err->getObjectName(), err->getObjectType());

  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report( const AT_Bounds_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *)s,
       "%s %lu is invalid",
       err->getObjectName(), err->getBadValue());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_Logic_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s,
       #ifndef NDEBUG
       "Logic error: %s (module %s at line %lu.)",
       err->getObjectName(), err->getModule(), err->getLineNum());
       #else
       "Logic error: %s",
       err->getObjectName());
       #endif
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_Corrupt_Error *const err)
{
  T_ExceptionString s;

  #ifndef NDEBUG
  wsprintfA( (char *) s,
       "Corruption error: %s %s (%lu)\n[module %s at line %lu]",
       err->getObjectType(), err->getObjectName(), err->getBadValue(), err->getModule(), err->getLineNum());
  #else
  if( err->getBadValue() != (uint32)-1)
    wsprintfA( (char *) s,
       "Corruption eror: %s %s (%lu)",
       err->getObjectType(), err->getObjectName(), err->getBadValue());
  else
    wsprintfA( (char *) s,
       "Corruption error: %s %s",
       err->getObjectType(), err->getObjectName());
  #endif
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_System_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s, "System error: error number %lu", err->getErrorNum());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_File_Open_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s, "Cannot open file %s", err->getObjectName());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_File_Type_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s, "Bad file type for %s", err->getObjectName());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_File_Read_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s, "Error reading file %s", err->getObjectName());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_File_Write_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s, "Error writing to  file %s", err->getObjectName());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_Constructor_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s, "Cannot create object %s", err->getObjectName());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_Function_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char*)s,
       "This function is not yet implemented. %s", err->getObjectName());
  pExceptionList->ExceptionPush(s);
}

void ErrorReporter::report(const AT_Unexpected_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char*)s,
       #ifndef NDEBUG
       "Unexpected error: module %s at line %lu. Object = %s, Type = %s",
       err->getModule(), err->getLineNum(), err->getObjectName(), err->getObjectType());
       #else
       "Unexpected error: module %s at line %lu.",
       err->getModule(), err->getLineNum());
       #endif
  pExceptionList->ExceptionPush(s);
}

/////////////////////////////////////////////////////////////////////////////////
// Exception Reports :: AT_Index_List
/////////////////////////////////////////////////////////////////////////////////
void IndexErrorReporter::report( const AT_Index_List::noIndex *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s,
       "Field has no data.");
  pExceptionList->ExceptionPush(s);
}

void IndexErrorReporter::report( const AT_Index_List::openError *const err)
{
  T_ExceptionString s;
  #ifndef NDEBUG
    wsprintfA( (char *) s,
       "Index %u not available.", err->getIndexNum());
  #else
    wsprintfA( (char *) s,
       "Index not available.");
  #endif
  pExceptionList->ExceptionPush(s);
}

void IndexErrorReporter::report(const AT_System_Error *const err)
{
  T_ExceptionString s;
    wsprintfA( (char *) s, "System error: error number %lu", err->getErrorNum());
  pExceptionList->ExceptionPush(s);
}

void IndexErrorReporter::report(const AT_Error *const err)
{

}

