//#####################################################################
// Copyright 2006-2009, Jon Gretarsson, Geoffrey Irving, Andrew Selle, Tamar Shinar, Eftychios Sifakis.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#include <Core/Meshes/STRUCTURE.h>
#include <Core/Log/LOG.h>
#include <Core/Read_Write/FILE_UTILITIES.h>
#include <Core/Registry/STRUCTURE_REGISTRY.h>
#include <Core/Vectors/VECTOR.h>
#include <climits>
namespace PhysBAM{
//#####################################################################
template<class TV> STRUCTURE<TV>& Representative(const std::string& name);
//#####################################################################
// Constructor
//#####################################################################
template<class TV> STRUCTURE<TV>::
STRUCTURE()
    :update_every_frame(false)
{}
//#####################################################################
// Destructor
//#####################################################################
template<class TV> STRUCTURE<TV>::
~STRUCTURE()
{}
//#####################################################################
// Function Create_From_Name
//#####################################################################
template<class TV> STRUCTURE<TV>* STRUCTURE<TV>::
Create_From_Name(const std::string& name)
{
    STRUCTURE* structure=STRUCTURE_REGISTRY<TV>::Name_To_Factory(name)->Create();
    if(!structure) throw VALUE_ERROR(LOG::sprintf("%s has no Create() function.",name.c_str()));
    return structure;
}
//#####################################################################
// Function Create_From_Name
//#####################################################################
template<class TV> STRUCTURE<TV>* STRUCTURE<TV>::
Create_From_Name(const std::string& name,GEOMETRY_PARTICLES<TV>& particles)
{
    STRUCTURE* structure=STRUCTURE_REGISTRY<TV>::Name_To_Factory(name)->Create(particles);
    if(!structure) throw VALUE_ERROR(LOG::sprintf("%s has no Create(GEOMETRY_PARTICLES<TV>& particles) function.",name.c_str()));
    return structure;
}
//#####################################################################
// Function Create_From_Fxtension
//#####################################################################
template<class TV> STRUCTURE<TV>* STRUCTURE<TV>::
Create_From_Extension(const std::string& extension)
{
    STRUCTURE* structure=STRUCTURE_REGISTRY<TV>::Extension_To_Factory(extension)->Create();
    if(!structure) throw VALUE_ERROR(LOG::sprintf("No Create() function matching extension %s",extension.c_str()));
    return structure;
}
//#####################################################################
// Function Rescale
//#####################################################################
template<class TV> void STRUCTURE<TV>::
Rescale(const T scaling_factor)
{
    PHYSBAM_FUNCTION_IS_NOT_DEFINED();
}
//#####################################################################
// Function Append_Particles_And_Create_Copy
//#####################################################################
template<class TV> STRUCTURE<TV>* STRUCTURE<TV>::
Append_Particles_And_Create_Copy(GEOMETRY_PARTICLES<TV>& particles,ARRAY<int>* particle_indices) const
{
    PHYSBAM_FUNCTION_IS_NOT_DEFINED();
}
//#####################################################################
// Function Update_Number_Nodes
//#####################################################################
template<class TV> void STRUCTURE<TV>::
Update_Number_Nodes()
{
}
//#####################################################################
// Function Mark_Nodes_Referenced
//#####################################################################
template<class TV> void STRUCTURE<TV>::
Mark_Nodes_Referenced(ARRAY<int>& marks,const int mark) const
{
}
//#####################################################################
// Function Name
//#####################################################################
template<class TV> std::string STRUCTURE<TV>::
Name() const
{
    PHYSBAM_WARN_IF_NOT_OVERRIDDEN();
    return Static_Name();
}
//#####################################################################
// Function Extension
//#####################################################################
template<class TV> std::string STRUCTURE<TV>::
Extension() const
{
    PHYSBAM_WARN_IF_NOT_OVERRIDDEN();
    return Static_Extension();
}
//#####################################################################
// Function Read_Structure
//#####################################################################
template<class TV> void STRUCTURE<TV>::
Read_Structure(TYPED_ISTREAM& input)
{
    std::string name;
    Get(input,'(');
    Read_Binary(input,name);
    if(name!=Name()){
        LOG::cerr<<"Trying to read in a "<<name<<" as a "<<Name()<<std::endl;
        PHYSBAM_FATAL_ERROR();}
    Read(input);
    Get(input,')');
}
//#####################################################################
// Function Write_Structure
//#####################################################################
template<class TV> void STRUCTURE<TV>::
Write_Structure(TYPED_OSTREAM& output) const
{
    Beg(output,'(');
    Write_Binary(output,Name());
    Write(output);
    End(output,')');
}
//#####################################################################
// Function Create_Structure
//#####################################################################
template<class TV> STRUCTURE<TV>*  STRUCTURE<TV>::
Create_Structure(TYPED_ISTREAM& input,GEOMETRY_PARTICLES<TV>& particles)
{
    std::string name;
    Read_Binary(input,name);
    STRUCTURE<TV>* structure=STRUCTURE<TV>::Create_From_Name(name,particles);
    structure->Read(input);
    return structure;
}
//#####################################################################
// Function Create_Structure
//#####################################################################
template<class TV> STRUCTURE<TV>*  STRUCTURE<TV>::
Create_Structure(TYPED_ISTREAM& input)
{
    std::string name;
    Read_Binary(input,name);
    STRUCTURE<TV>* structure=STRUCTURE<TV>::Create_From_Name(name);
    structure->Read(input);
    return structure;
}
//#####################################################################
// Function Create_From_File
//#####################################################################
template<class TV> STRUCTURE<TV>*  STRUCTURE<TV>::
Create_From_File(const std::string& filename)
{
    STRUCTURE<TV>* structure=STRUCTURE<TV>::Create_From_Extension(Get_File_Extension(filename));
    Read_From_File(filename,*structure);
    return structure;
}
//#####################################################################
// Function Read_Structure_Array
//#####################################################################
template<class TV> void
Read_Structure_Array(TYPED_ISTREAM& input,ARRAY<STRUCTURE<TV>*>& a)
{
    if(input.type==STREAM_TYPE::type_text)
    {
        Get(input,'(');
        while(!Try_Get(input,')'))
            a.Append(STRUCTURE<TV>::Create_Structure(input));
    }
    else
    {
        int num;
        Read_Binary(input,num);
        a.Resize(num);
        for(int i=0;i<num;i++)
            a(i)=STRUCTURE<TV>::Create_Structure(input);
    }
}
//#####################################################################
// Function Write_Structure_Array
//#####################################################################
template<class TV> void
Write_Structure_Array(TYPED_OSTREAM& output,const STRUCTURE<TV>** ptr,int num)
{
    if(output.type!=STREAM_TYPE::type_text)
        Write_Binary(output,num);
    Beg(output,'(');
    for(int i=0;i<num;i++)
        ptr[i]->Write_Structure(output);
    End(output,')');
}
//#####################################################################
template class STRUCTURE<VECTOR<float,1> >;
template class STRUCTURE<VECTOR<float,2> >;
template class STRUCTURE<VECTOR<float,3> >;
template class STRUCTURE<VECTOR<double,1> >;
template class STRUCTURE<VECTOR<double,2> >;
template class STRUCTURE<VECTOR<double,3> >;
template void Write_Structure_Array<VECTOR<double,1> >(TYPED_OSTREAM&,STRUCTURE<VECTOR<double,1> > const**,int);
template void Write_Structure_Array<VECTOR<double,2> >(TYPED_OSTREAM&,STRUCTURE<VECTOR<double,2> > const**,int);
template void Write_Structure_Array<VECTOR<double,3> >(TYPED_OSTREAM&,STRUCTURE<VECTOR<double,3> > const**,int);
template void Write_Structure_Array<VECTOR<float,1> >(TYPED_OSTREAM&,STRUCTURE<VECTOR<float,1> > const**,int);
template void Write_Structure_Array<VECTOR<float,2> >(TYPED_OSTREAM&,STRUCTURE<VECTOR<float,2> > const**,int);
template void Write_Structure_Array<VECTOR<float,3> >(TYPED_OSTREAM&,STRUCTURE<VECTOR<float,3> > const**,int);
template void Read_Structure_Array<VECTOR<double,1> >(TYPED_ISTREAM&,ARRAY<STRUCTURE<VECTOR<double,1> >*,int>&);
template void Read_Structure_Array<VECTOR<double,2> >(TYPED_ISTREAM&,ARRAY<STRUCTURE<VECTOR<double,2> >*,int>&);
template void Read_Structure_Array<VECTOR<double,3> >(TYPED_ISTREAM&,ARRAY<STRUCTURE<VECTOR<double,3> >*,int>&);
template void Read_Structure_Array<VECTOR<float,1> >(TYPED_ISTREAM&,ARRAY<STRUCTURE<VECTOR<float,1> >*,int>&);
template void Read_Structure_Array<VECTOR<float,2> >(TYPED_ISTREAM&,ARRAY<STRUCTURE<VECTOR<float,2> >*,int>&);
template void Read_Structure_Array<VECTOR<float,3> >(TYPED_ISTREAM&,ARRAY<STRUCTURE<VECTOR<float,3> >*,int>&);
}
