//#####################################################################
// Copyright 2005, Eran Guendelman, Andrew Selle.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class GRID_ITERATOR_BASE
//#####################################################################
// Serves as base for node and cell iterators
//#####################################################################
#ifndef __GRID_ITERATOR_BASE__
#define __GRID_ITERATOR_BASE__
#include <Core/Grids/GRID.h>
#include <Core/Utilities/PHYSBAM_ATTRIBUTE.h>

namespace PhysBAM{

template<class TV>
class GRID_ITERATOR_BASE
{
    typedef VECTOR<int,TV::m> IV;
protected:
    int number_of_regions,current_region;
    RANGE<IV> region,regions[1<<TV::m]; // at most 2^d distinct regions for iteration
    IV index;
    bool valid;

    GRID_ITERATOR_BASE();
    GRID_ITERATOR_BASE(const RANGE<IV>& region_input);

    void Reset_Regions()
    {number_of_regions=0;}

    void Add_Region(const RANGE<IV>& region_input)
    {assert(number_of_regions<(1<<TV::m));
    if(TV::m==0) return;
    if(region_input.Edge_Lengths().Min()>=0) regions[number_of_regions++]=region_input;}

    void Reset(const int region_index=0)
    {if(TV::m==0){valid=true;index=IV();return;}
    valid=(region_index<number_of_regions);if(valid){current_region=region_index;region=regions[current_region];index=region.Minimum_Corner();}}

public:
    bool Valid() const
    {return valid;}

    void Next() PHYSBAM_ALWAYS_INLINE
    {if(TV::m==0){valid=false;return;}
    if(index(TV::m-1)<region.max_corner(TV::m-1)-1) index(TV::m-1)++;else Next_Helper();}

protected:
    void Next_Helper();
};
//#####################################################################
}
#endif
