#include <catch2/catch_all.hpp>

#include <Kokkos_Core.hpp>

#include <language/utils/OperatorRepository.hpp>
#include <mesh/DiamondDualConnectivityManager.hpp>
#include <mesh/DiamondDualMeshManager.hpp>
#include <mesh/MeshDataManager.hpp>
#include <mesh/SynchronizerManager.hpp>
#include <utils/Messenger.hpp>
#include <utils/PETScWrapper.hpp>
#include <utils/RandomEngine.hpp>
#include <utils/SLEPcWrapper.hpp>

#include <MeshDataBaseForTests.hpp>

int
main(int argc, char* argv[])
{
  parallel::Messenger::create(argc, argv);
  Kokkos::initialize({4, -1, -1, true});

  PETScWrapper::initialize(argc, argv);
  SLEPcWrapper::initialize(argc, argv);

  Catch::Session session;
  int result = session.applyCommandLine(argc, argv);

  if (result == 0) {
    const auto& config = session.config();
    if (config.listReporters() or config.listTags() or config.listTests()) {
      result = session.run();
    } else {
      // Disable outputs from tested classes to the standard output
      std::cout.setstate(std::ios::badbit);

      SynchronizerManager::create();
      RandomEngine::create();
      MeshDataManager::create();
      DiamondDualConnectivityManager::create();
      DiamondDualMeshManager::create();

      MeshDataBaseForTests::create();

      OperatorRepository::create();

      result = session.run();

      OperatorRepository::destroy();

      MeshDataBaseForTests::destroy();

      DiamondDualMeshManager::destroy();
      DiamondDualConnectivityManager::destroy();
      MeshDataManager::destroy();
      RandomEngine::destroy();
      SynchronizerManager::destroy();
    }
  }

  SLEPcWrapper::finalize();
  PETScWrapper::finalize();

  Kokkos::finalize();
  parallel::Messenger::destroy();

  return result;
}