//
// Created by jholder on 21.10.21.
//

#pragma once

#include "Data/Rod2d.hpp"
#include "Data/Simulation.h"

class Integratoren2d {
    using Vector = Eigen::Vector2d;

   public:
    using force_t =  std::function<Vector(Vector, Vector)>;
    using torque_t = std::function<double(Eigen::Vector2d, Eigen::Vector2d)>;
    using integrator_t = std::function < void(Rod2d &, Simulation &,
                                              const force_t &,
                                              const torque_t & )>;

    static void Set1_Euler_f(
        Rod2d &rod2D, Simulation &sim,
        const std::function<Vector(Vector, Vector)> &force,
        const std::function<double(Vector, Vector)> &torque);

    static void Set1_Euler(Rod2d &rod2D, Simulation &sim);

    static void Set2_Heun_f(
        Rod2d &rod2D, Simulation &sim,
        const std::function<Vector(Vector, Vector)> &force,
        const std::function<double(Vector, Vector)> &torque);

    static void Set2_Heun(Rod2d &rod2D, Simulation &sim);

    static void Set3_Exact_f(
        Rod2d &rod2D, Simulation &sim,
        const std::function<Eigen::Vector2d(Eigen::Vector2d, Eigen::Vector2d)>
            &force,
        const std::function<double(Eigen::Vector2d, Eigen::Vector2d)> &torque);

    static void Set3_Exact(Rod2d &rod2D, Simulation &sim);

    static void Set4_BDAS_f(
        Rod2d &rod2D, Simulation &sim,
        const std::function<Eigen::Vector2d(Eigen::Vector2d, Eigen::Vector2d)>
            &force,
        const std::function<double(Eigen::Vector2d, Eigen::Vector2d)> &torque);

    static void Set4_BDAS(Rod2d &rod2D, Simulation &sim);

    static void Set5_MBD_f(
        Rod2d &rod2D, Simulation &sim,
        const std::function<Eigen::Vector2d(Eigen::Vector2d, Eigen::Vector2d)>
            &force,
        const std::function<double(Eigen::Vector2d, Eigen::Vector2d)> &torque);

    static void Set5_MBD(Rod2d &rod2D, Simulation &sim);
};
