// ---------------------------------------------------------------------
//   Exception.h (created on Tue Aug 23 01:08:35 BRT 2005)
// 
//   Genetic Algorithm File Fitter (gaffitter)
//
//   Copyright (C) 2005-2015 Douglas A. Augusto
// 
// This file is part of gaffitter.
// 
// gaffitter is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at
// your option) any later version.
// 
// gaffitter is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with gaffitter; if not, see <http://www.gnu.org/licenses/>.
//
// ---------------------------------------------------------------------

#ifndef exception_hh
#define exception_hh 

#include <string>
#include <sstream>
#include <exception>

//----------------------------------------------------------------------
#ifdef NDEBUG
const bool debug = false;
#else 
const bool debug = true;
#endif

class E_Exception;

//----------------------------------------------------------------------
/**
 * Exception base class.
 */
class E_Exception: std::exception { 
public:
  /**
   * Create an exception with an optional message "L" and an
   * error message "M".
   */
  E_Exception(const std::string& L = "", const std::string& M = "")
            : m_msg( M ), m_loc( L ) {}

  virtual ~E_Exception() throw() {};
  /** 
   * Return the user message. 
  */
  virtual const char * local() { return m_loc.c_str(); }
  /**
   * Return the error message.
   */
  virtual const char * what() const throw() { return m_msg.c_str(); }

protected:
  std::string m_msg; /**< The error message. */
  std::string m_loc; /**< Optional message, such as the name of the
                          function where throw was called. */
};

//----------------------------------------------------------------------
inline std::ostream&
operator<<( std::ostream& o, const E_Exception& e )
{
   o << '\n' << "> Error: " << e.what() << std::endl;
   return o;
}

//-----------------------------------------------------------------------------
class E_NoInputFiles : public E_Exception {
public:  
   E_NoInputFiles ( const std::string& loc = "" )
      : E_Exception (loc, "No input to process") {};
};

//-----------------------------------------------------------------------------
class E_BigInput : public E_Exception {
public:  
   E_BigInput ( const std::string& loc = "" )
      : E_Exception (loc, "Too many input files/items") {};
};

//-----------------------------------------------------------------------------
class E_NoTarget : public E_Exception {
public:  
   E_NoTarget (const std::string& app = "fit"): E_Exception ("", 
         "Missing '--target' (Try '"+app+" -h' for more information)") {};
};

//-----------------------------------------------------------------------------
template<class X, class A> inline void Assert(A expression)
{
   if (debug && !expression) throw X();
} 

inline void Assert(bool expression)
{
   Assert<E_Exception>(expression);
}

//-----------------------------------------------------------------------------
#endif
