// $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/src/tiptilt_ctrl/bcu/util/Assertions.h 978 2018-10-31 09:32:42Z depa $
#pragma once

#include <string>


namespace Sharknir {

/**
 * @brief This class is useful for a design by contract programming style.
 *
 *        It is recommended to use the following macros:
 *
 *        \li ARGOS_PRECONDITION()
 *        \li ARGOS_POSTCONDITION()
 *        \li ARGOS_INVARIANT()
 *        \li ARGOS_ENSURE()
 *
 *        \c ARGOS_ENSURE() is better than \c assert() because
 *        it is independent of the \c NDEBUG definition.  Thus,  even
 *        in release code,  \c ARGOS_ENSURE evaluates the given condition.
 *        The function \c assert() only works if \c NDEBUG is missing.
 */
class Condition {
public:
    /**
     * @brief Verify that the boolean condition is fulfilled.
     *
     * @warning Do not use this method!
     *          Use a macro version instead (e.g. \c ARGOS_ENSURE)!
     */
    static void check(const std::string& conditionTypeName,
            bool condition, const std::string& literalCondition,
            const std::string& message, const char *filename, int lineNr);

private:
    static void printErrorMessage(const std::string conditionTypeName,
            const std::string literalCondition, const std::string& message,
            const char *filename, int lineNr);
};

/**
 * @brief Defines a precondition.
 *
 * @param condition a boolean expression.
 * @param message a user-friendly description of this precondition.
 */
#define SHARKNIR_PRECONDITION(condition, message) \
    ::Sharknir::Condition::check("Precondition", (condition), #condition, message, __FILE__, __LINE__)

/**
 * @brief Defines a postcondition.
 *
 * @param condition a boolean expression.
 * @param message a user-friendly description of this postcondition
 */
#define SHARKNIR_POSTCONDITION(condition, message) \
    ::Sharknir::Condition::check("Postcondition", (condition), #condition, message, __FILE__, __LINE__)

/**
 * @brief Defines an invariant.
 *
 * @param condition a boolean expression.
 * @param message a user-friendly description of this check.
 */
#define SHARKNIR_INVARIANT(condition, message) \
    ::Sharknir::Condition::check("Invariant", (condition), #condition, message, __FILE__, __LINE__)

/**
 * @brief Defines an everlasting \c assert().
 *
 * @param condition a boolean expression.
 * @param message a user-friendly description of this check.
 */
#define SHARKNIR_ENSURE(condition, message) \
    ::Sharknir::Condition::check("Condition", (condition), #condition, message, __FILE__, __LINE__)
}

