//========================================================================================
// (C) (or copyright) 2021. Triad National Security, LLC. All rights reserved.
//
// This program was produced under U.S. Government contract 89233218CNA000001 for Los
// Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC
// for the U.S. Department of Energy/National Nuclear Security Administration. All rights
// in the program are reserved by Triad National Security, LLC, and the U.S. Department
// of Energy/National Nuclear Security Administration. The Government is granted for
// itself and others acting on its behalf a nonexclusive, paid-up, irrevocable worldwide
// license in this material to reproduce, prepare derivative works, distribute copies to
// the public, perform publicly and display publicly, and to permit others to do so.
//========================================================================================

#include "driver/driver.hpp"
#include "parthenon_manager.hpp"

#include "sparse_advection_driver.hpp"

int main(int argc, char *argv[]) {
  using parthenon::DriverStatus;
  using parthenon::ParthenonManager;
  using parthenon::ParthenonStatus;
  ParthenonManager pman;

  // Redefine parthenon defaults
  pman.app_input->ProcessPackages = sparse_advection_example::ProcessPackages;
  pman.app_input->ProblemGenerator = sparse_advection_example::ProblemGenerator;
  pman.app_input->PostStepDiagnosticsInLoop =
      sparse_advection_example::PostStepDiagnosticsInLoop;

  // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up
  auto manager_status = pman.ParthenonInit(argc, argv);
  if (manager_status == ParthenonStatus::complete) {
    pman.ParthenonFinalize();
    return 0;
  }
  if (manager_status == ParthenonStatus::error) {
    pman.ParthenonFinalize();
    return 1;
  }
  // Now that ParthenonInit has been called and setup succeeded, the code can now
  // make use of MPI and Kokkos

  DriverStatus driver_status;
  // This needs to be scoped so that the driver object is destructed before Finalize
  {
    // Initialize the driver
    sparse_advection_example::SparseAdvectionDriver driver(
        pman.pinput.get(), pman.app_input.get(), pman.pmesh.get());

    // This line actually runs the simulation
    driver_status = driver.Execute();
  }
  // call MPI_Finalize and Kokkos::finalize if necessary
  pman.ParthenonFinalize();

  // MPI and Kokkos can no longer be used

  if (driver_status == DriverStatus::complete) {
    return 0;
  } else if (driver_status == DriverStatus::timeout) {
    return 1;
  } else if (driver_status == DriverStatus::failed) {
    return 2;
  } else {
    return 3;
  }
}
