// ****************************************************************************
//
//          Aevol - An in silico experimental evolution platform
//
// ****************************************************************************
//
// Copyright: See the AUTHORS file provided with the package or <www.aevol.fr>
// Web: http://www.aevol.fr/
// E-mail: See <http://www.aevol.fr/contact/>
// Original Authors : Guillaume Beslon, Carole Knibbe, David Parsons
//
// This program 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 2 of the License, or
// (at your option) any later version.
//
// This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
//
// ****************************************************************************

#ifndef AEVOL_UTILS_H_
#define AEVOL_UTILS_H_

#include <cinttypes>
#include <cassert>
#include <cstdlib>

#include <format>
#include <iostream>
#include <string>

#include "aevol_version.h"

namespace aevol {

template <typename T, typename T2>
T mod(T a, T2 b);

[[noreturn]] void exit_with_usr_msg(const std::string& msg);
[[noreturn]] void exit_with_dev_msg(const std::string& msg, const std::string& file, int line);
void print_aevol_version();
void check_posix_memalign(int status);
auto time_string() -> std::string;

template <typename T, typename T2>
T mod(T a, T2 b) {
  while (a < 0)  a += b;
  return a % b;
}

/**
 * Print an error message and exit (with error status)
 *
 * \param msg message to be printed
 * \param file should be __FILE__
 * \param line should be __LINE__
 */
[[noreturn]] inline void exit_with_dev_msg(const std::string& msg, const std::string& file, int line) {
  std::cout << file << ":" << line << ": error: " << msg << std::endl;
  exit(EXIT_FAILURE);
}

/**
 * Print an error message and exit (with error status)
 *
 * \param msg message to be printed
 */
[[noreturn]] inline void exit_with_usr_msg(const std::string& msg) {
  std::cout << "error: " << msg << std::endl;
  exit(EXIT_FAILURE);
}

/**
 * Print aevol version number
 */
inline void print_aevol_version() {
  std::cout << std::format("aevol {}\n", aevol::version_string);
}

}  // namespace aevol

#endif // AEVOL_UTILS_H_
