//#####################################################################
// Copyright 2009, Nipun Kwatra.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#include <Solids/Examples_And_Drivers/DRIVER.h>
#include <Core/Log/DEBUG_SUBSTEPS.h>
#include <Core/Log/LOG.h>
#include <Core/Log/SCOPE.h>
#include <Core/Read_Write/FILE_UTILITIES.h>
#include <Solids/Examples_And_Drivers/EXAMPLE.h>
using namespace PhysBAM;
//#####################################################################
// DRIVER
//#####################################################################
template<class TV> DRIVER<TV>::
DRIVER(EXAMPLE<TV>& example)
    :time(0),example(example),current_frame(0)
{
    DEBUG_SUBSTEPS::write_substeps_level=example.write_substeps_level;
    DEBUG_SUBSTEPS::writer=[this](const std::string& title,int level){this->example.viewer_output.Write_Substep(title,level);};
}
//#####################################################################
// ~DRIVER
//#####################################################################
template<class TV> DRIVER<TV>::
~DRIVER()
{
    DEBUG_SUBSTEPS::writer=0;
}
//#####################################################################
// Execute_Main_Program
//#####################################################################
template<class TV> void DRIVER<TV>::
Execute_Main_Program()
{
    Initialize();
    Simulate_To_Frame(example.last_frame);
}
//#####################################################################
// Initialize
//#####################################################################
template<class TV> void DRIVER<TV>::
Initialize()
{
    if(example.auto_restart){
        example.viewer_dir.Read_Last_Frame(0);
        example.restart=example.viewer_dir.frame_stack(0);}
    else if(example.restart)
        example.viewer_dir.Set(example.restart);
    if(example.restart) example.viewer_dir.Make_Common_Directory(true);
    current_frame=example.restart;
    time=example.Time_At_Frame(current_frame);
}
//#####################################################################
// Simulate_To_Frame
//#####################################################################
template<class TV> void DRIVER<TV>::
Simulate_To_Frame(const int frame)
{
    while(current_frame<frame){
        LOG::SCOPE scope("FRAME","Frame %d",current_frame+1);
        Advance_To_Target_Time(example.Time_At_Frame(current_frame+1));
        {
            LOG::SCOPE scope("writing output files");
            example.viewer_output.Flush_Frame("");
        }
        current_frame++;}
}
//#####################################################################
// Function Register_Output_Files
//#####################################################################
template<class TV> void DRIVER<TV>::
Register_Output_Files()
{
    example.Register_Output_Files();
    example.viewer_output.Add([this]()
    {Write_To_File(example.stream_type,example.viewer_dir.Frame_File("time"),time);},false);
}
//#####################################################################
namespace PhysBAM{
template class DRIVER<VECTOR<float,1> >;
template class DRIVER<VECTOR<float,2> >;
template class DRIVER<VECTOR<float,3> >;
template class DRIVER<VECTOR<double,1> >;
template class DRIVER<VECTOR<double,2> >;
template class DRIVER<VECTOR<double,3> >;
}
