#ifndef SRC_GRIDCONSTRUCTOR_HH
#define SRC_GRIDCONSTRUCTOR_HH

#include <dune/grid/common/gridfactory.hh>

#include <dune/fufem/geometry/convexpolyhedron.hh>
#include <dune/fufem/geometry/polyhedrondistance.hh>

#include "../../utils/diameter.hh"

template <class GridType>
class GridConstructor {
    private:
        double computeAdmissibleDiameter(double distance, double smallestDiameter, double lengthScale) {
            return (distance / 0.0125 / lengthScale + 1.0) * smallestDiameter;
        }

    public:
        GridConstructor() {}

        std::shared_ptr<GridType> grid() {
            return grid_;
        }

        template <class LocalVector>
        void refine(const ConvexPolyhedron<LocalVector>& weakPatch, double smallestDiameter, double lengthScale) {
            bool needRefine = true;
            while (true) {
              needRefine = false;
              for (auto &&e : elements(grid_->leafGridView())) {
                auto const geometry = e.geometry();

                auto const weakeningRegionDistance =
                    distance(weakPatch, geometry, 1e-6 * lengthScale);
                auto const admissibleDiameter =
                    computeAdmissibleDiameter(weakeningRegionDistance, smallestDiameter, lengthScale);

                if (diameter(geometry) <= admissibleDiameter)
                  continue;

                needRefine = true;
                grid_->mark(1, e);
              }
              if (!needRefine)
                break;

              grid_->preAdapt();
              grid_->adapt();
              grid_->postAdapt();
            }
        }

        virtual void createGrid() = 0;

    private:
        Dune::GridFactory<GridType> gridFactory_;
        std::shared_ptr<GridType> grid_;
};




#endif