//#####################################################################
// Copyright 2004-2007, Ron Fedkiw, Geoffrey Irving, Nipun Kwatra, Frank Losasso, Tamar Shinar.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class SOLIDS_EXAMPLE
//#####################################################################
#ifndef __SOLIDS_EXAMPLE__
#define __SOLIDS_EXAMPLE__

#include <Core/Geometry_Particles/DEBUG_PARTICLES.h>
#include <Core/Interpolation/AVERAGING_UNIFORM.h>
#include <Core/Log/DEBUG_SUBSTEPS.h>
#include <Core/Log/DEBUG_UTILITIES.h>
#include <Rigids/Rigid_Bodies/RIGID_BODY.h>
#include <Solids/Examples_And_Drivers/EXAMPLE.h>
#include <Solids/Forces_And_Torques/EXAMPLE_FORCES_AND_VELOCITIES.h>
#include <Solids/Solids_Evolution/SOLIDS_EVOLUTION_CALLBACKS.h>
namespace PhysBAM{

template<class TV> class SOLIDS_PARAMETERS;
template<class TV> class SOLIDS_EVOLUTION;
template<class TV> class SOLID_BODY_COLLECTION;

template<class TV>
class SOLIDS_EXAMPLE:public EXAMPLE<TV>,public EXAMPLE_FORCES_AND_VELOCITIES<TV>,public SOLIDS_EVOLUTION_CALLBACKS<TV>
{
    typedef typename TV::SCALAR T;
    typedef typename TV::SPIN T_SPIN;
    typedef EXAMPLE<TV> BASE;typedef VECTOR<int,TV::m> IV;
    typedef VECTOR<int,TV::m> T_VECTOR_INT;
    typedef ARRAY<char,IV> T_ARRAYS_CHAR;
    typedef typename TV::SPIN T_ANGULAR_VELOCITY;
    typedef AVERAGING_UNIFORM<TV> T_AVERAGING;
public:
    using BASE::frame_title;using BASE::stream_type;using BASE::last_frame;using BASE::frame_dt;
    using BASE::write_substeps_level;using BASE::Set_Write_Substeps_Level;
    using BASE::restart;using BASE::viewer_dir;using BASE::viewer_output;

protected:
    T minimum_collision_thickness; // needed for ray tracing, etc.
public:
    SOLIDS_PARAMETERS<TV>& solids_parameters;
    SOLID_BODY_COLLECTION<TV>& solid_body_collection;
    SOLIDS_EVOLUTION<TV>* solids_evolution; // defaults to newmark
    DEBUG_PARTICLES<TV>& debug_particles;
    bool opt_skip_debug_data;
    int test_number=0;

    SOLIDS_EXAMPLE(const STREAM_TYPE stream_type,PARSE_ARGS& parse_args);
    SOLIDS_EXAMPLE(const SOLIDS_EXAMPLE&) = delete;
    void operator=(const SOLIDS_EXAMPLE&) = delete;
    virtual ~SOLIDS_EXAMPLE();

    void Set_Minimum_Collision_Thickness(const T minimum_collision_thickness_input=1e-6)
    {minimum_collision_thickness=minimum_collision_thickness_input;}

//#####################################################################
    virtual void Post_Initialization();
    virtual void Preprocess_Frame(const int frame);
    virtual void Postprocess_Frame(const int frame);
    virtual void Preprocess_Substep(const T dt,const T time);
    virtual void Postprocess_Substep(const T dt,const T time);
    void Log_Parameters() const override;
    // solids
    virtual void Initialize_Bodies();
    virtual void Read_Output_Files_Solids();
    void Post_Velocity_Advection_Callback(const T dt,const T time){}
    void Register_Output_Files() override;
//#####################################################################
};
}
#endif
