// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1993 
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        error.C
// 
// Purpose:     generic hyperg error
// 
// Created:     29 Nov 93   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// 
// </file> 
#include "error.h"

#include "assert.h"
#include "language.h"

#include <hyperg/utils/str.h>

#include <Dispatch/rpcstream.h>



#define VERBOSE
#include "verbose.h"



// --------------------------------------------------------------------
ErrorBase::ErrorClass ErrorBase::classId (int code) {
   int tmp = (0xFF00 & code) >> 8 ;
   return tmp>=HG && tmp<NCLASSES  ?  ErrorClass(tmp)  :  NCLASSES ;
}

int ErrorBase::realCode (int code) {
   return 0xFF & code ;
}

// --------------------------------------------------------------------
const ErrorBase* Error::errcl_[ErrorBase::NCLASSES] = {nil};

const char* Error::notusedstr_ = "not a used error class" ;
const char* Error::notvalidstr_ = "not a valid error class" ;

const int Error::ok_digit_ = 0 ;


Error :: Error() : code_(-1) {}
Error :: Error (int code) : code_(code) {}
Error :: Error (const Error& e) : code_(e.code_) {}

ErrorBase::ErrorClass Error :: classId() const {
   if (code_ == -1) 
      return ErrorBase::NCLASSES ;
   return ErrorBase::classId (code_) ;
}

const char* Error :: className (int language) const {
   // language not supported for the time being
   ErrorBase::ErrorClass cl = ErrorBase::classId (code_) ;
   hgassert (cl>=ErrorBase::HG && cl<=ErrorBase::NCLASSES, 
             "Error::className(): not a valid error class") ;
   if (cl == ErrorBase::NCLASSES)
      return notvalidstr_ ;
   return errcl_[cl] ? errcl_[cl]->getClassName(language) : notusedstr_ ;
}

const char* Error :: description (int language) const {
   ErrorBase::ErrorClass cl = ErrorBase::classId (code_) ;
   hgassert (cl>=ErrorBase::HG && cl<=ErrorBase::NCLASSES, 
             "Error::description(): not a valid error class ") ;
   if (cl == ErrorBase::NCLASSES)
      return notvalidstr_ ;
   return errcl_[cl] ? errcl_[cl]->getDescription (code_, language) : notusedstr_ ;
}

boolean Error :: ok() const {
   ErrorBase::ErrorClass cl = ErrorBase::classId (code_) ;
   hgassert (cl>=ErrorBase::HG && cl<=ErrorBase::NCLASSES, 
             "Error::ok(): not a valid error class") ;
   DEBUGNL ("Error::ok(): class "<<className(HgLanguage::Default)) ;
   if (cl == ErrorBase::NCLASSES)
      return false ;
   return ErrorBase::realCode(code_) == ok_digit_ ;
//    return errcl_[cl] ? errcl_[cl]->getOk (code_) : false ;
}

void Error :: use (const ErrorBase* e) {
   ErrorBase::ErrorClass cl = e->getClassId() ;
   hgassert (e->okDigit()==ok_digit_, "Error::use(): OK is not zero") ;
   hgassert (cl>=ErrorBase::HG && cl<ErrorBase::NCLASSES, "Error::use(): not a valid error class") ;
   if (cl>=ErrorBase::HG && cl<ErrorBase::NCLASSES)
      errcl_[cl] = e ;
}

rpcstream& operator << (rpcstream& s, Error e) {
     s.operator<<(e.code_) ;
     return s;
}
rpcstream& operator >> (rpcstream& s, class Error& e) {
     s.operator>>(e.code_);
     return s ;
}
