//#####################################################################
// Copyright 2025, Mehrnaz Ayazi
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class BOUNDARY_CONDITION
//#####################################################################
#ifndef __BOUNDARY_CONDITION__
#define __BOUNDARY_CONDITION__
#include <Core/Vectors/VECTOR.h>
#include <Hybrid_Methods/Regions/REGION_ARRAY.h>
#include <Hybrid_Methods/Examples_And_Drivers/MPM_HELPERS.h>
#include <Core/Boundaries/BOUNDARY_PERIODIC.h>
#include <Core/Grids/GRID.h>

namespace PhysBAM{
enum class RI;

template<class TV>
class BOUNDARY_CONDITION
{
    typedef typename TV::SCALAR T;
    typedef VECTOR<int,TV::m> IV;
public:
    REGION_ARRAY<T,IV>& reflect_mass;//I think we don't need to pass these
    REGION_ARRAY<TV,IV>& reflect_momentum;//I think we don't need to pass these
    VECTOR<MPM::BC_TYPE,TV::m*2>& side_bc_type; // -x, +x, -y, +y, -z, +z
    bool test_bc;
    T& friction;
    GRID<TV> &grid;
    int& ghost;
    VECTOR<bool,TV::m>& is_periodic;

    REGION_ARRAY<TV,IV> bc_test_velocity;
    bool test_bc_visit_nodes=false;
    
    BOUNDARY_CONDITION(REGION_ARRAY<T,IV>& reflect_mass,REGION_ARRAY<TV,IV>& reflect_momentum,VECTOR<MPM::BC_TYPE,TV::m*2>& side_bc_type,
        bool test_bc,T& friction,GRID<TV> &grid,int& ghost,VECTOR<bool,TV::m>& is_periodic);
    virtual ~BOUNDARY_CONDITION();
    void Reflect_Boundary_Friction(const REGION_ARRAY<T,IV>& mass,REGION_ARRAY<TV,IV>& velocity);
    void Test_Reflect_Boundary(const REGION_ARRAY<T,IV>& mass,REGION_ARRAY<TV,IV>& v0,REGION_ARRAY<TV,IV>& v1);
    void Test_Boundary_Friction(const REGION_ARRAY<T,IV>& mass,REGION_ARRAY<TV,IV>& velocity);
    void Visit_Nodes(RI flags,const REGION_ARRAY<T,IV>& a,
        const std::function<void(int side,const REGION_INDEX<IV::m>& in,
        const REGION_INDEX<IV::m>& out)>& f,
        const std::function<void(int side,const REGION_INDEX<IV::m>& in)>& bf) const;
    template<class T2> void Fix_Periodic(ARRAY_VIEW<T2,IV> u) const;
    template<class T2,class OP> void Fix_Periodic_Accum(ARRAY_VIEW<T2,IV> u,const OP& op) const;
//#####################################################################
};
}
#endif
