#ifndef BIBUNU_EXCEPTION_H
#define BIBUNU_EXCEPTION_H

#include <exception>
#include <vector>
#include <string>

namespace bibunu
{

class Exception: public std::exception
{
public:
   Exception();

   // Trivially copyable and movable because only member is a vector.
   Exception(const Exception&) = default;
   Exception(Exception&&) = default;

   virtual const char *what() const noexcept;

   void addContext(std::string context);
   std::string generateMessage() const;

   const std::vector<std::string> &contextTrace() const;

   void throwWithContext(std::string context);

   virtual ~Exception();
private:
   std::vector<std::string> _context_trace;
};

// Simple exception with a message.
class GeneralException : public Exception
{
public:
   GeneralException(std::string error_message);

   // Trivially copyable and movable because only member is a string.
   GeneralException(const GeneralException&) = default;
   GeneralException(GeneralException&&) = default;

   virtual const char *what() const noexcept;

   virtual ~GeneralException();
private:
   std::string _error_message;
};

}

#endif // BIBUNU_EXCEPTION_H
