#ifndef DUNE_TECTONIC_TIMESTEPPING_HH
#define DUNE_TECTONIC_TIMESTEPPING_HH

#include "enums.hh"
#include <dune/common/bitsetvector.hh>

template <class Vector, class Matrix, class Function, size_t dim>
class TimeSteppingScheme {
public:
  void virtual nextTimeStep() = 0;
  void virtual setup(Vector const &ell, double _tau, double relativeTime,
                     Vector &rhs, Vector &iterate, Matrix &AB) = 0;

  void virtual postProcess(Vector const &iterate) = 0;
  void virtual extractDisplacement(Vector &displacement) const = 0;
  void virtual extractVelocity(Vector &velocity) const = 0;
};

#include "timestepping/newmark.hh"
#include "timestepping/backward_euler.hh"

template <class Vector, class Matrix, class Function, int dimension>
std::shared_ptr<TimeSteppingScheme<Vector, Matrix, Function, dimension>>
initTimeStepper(Config::scheme scheme,
                Function const &velocityDirichletFunction,
                Dune::BitSetVector<dimension> const &velocityDirichletNodes,
                Matrix const &massMatrix, Matrix const &stiffnessMatrix,
                Matrix const &dampingMatrix, Vector const &u_initial,
                Vector const &v_initial, Vector const &a_initial) {
  switch (scheme) {
    case Config::Newmark:
      return std::make_shared<Newmark<Vector, Matrix, Function, dimension>>(
          stiffnessMatrix, massMatrix, dampingMatrix, u_initial, v_initial,
          a_initial, velocityDirichletNodes, velocityDirichletFunction);
    case Config::BackwardEuler:
      return std::make_shared<
          BackwardEuler<Vector, Matrix, Function, dimension>>(
          stiffnessMatrix, massMatrix, dampingMatrix, u_initial, v_initial,
          velocityDirichletNodes, velocityDirichletFunction);
    default:
      assert(false);
  }
}

#endif