#ifndef INITIAL_TRIANG_HH
#define INITIAL_TRIANG_HH

#include "CommandlineOptions.hh"
#include "FlipChecker.hh"
#include "TriangNode.hh"
#include "GKZ.hh"
#include "FlipChecker.hh"

// template<bool trivialSymmetry, bool checkFine, bool smallGroup, typename APCType>
template<typename FlipDataType, typename APCType>
class InitialTriangFinder {

   private:
      using FlipChecker = typename FlipDataType::Checker;
      using pmFlipContainer = typename APCType::pmFlipContainer;
      const APCType& apc;


      // Determine whether a triangulation has a possible upflip. If yes, then
      // the lex maximal upflip will be stored in frout and true is returned.
      // We store the flips marked by mark_flips for further use.
      bool has_upflip(const FlipDataType& fd, Flip& frout) const {
         const pmFlipContainer& UP(fd.get_upflips());
         int s = UP.size();
         if(s > 0){
            frout = (UP.back()).second;
            return true;
         }
         return false;
      }

      TriangNode walk_to_root(const TriangNode& initial, const FlipChecker& fc) const{
         TriangNode result(initial);
         FlipDataType fd(apc, result, fc);
         Flip flip;
         while(has_upflip(fd, flip)){
            result = TriangNode(0, result, flip);
            fd.mutate(flip);
         }
         return result;
      }



      TriangNode set_path(const TriangNode& initial) const{
         TriangNode result(initial);
         FlipChecker fc(apc.get_points(), apc.get_chiro());
         return walk_to_root(initial, fc);
         /*
         if(CommandlineOptions::check_regular()){
            typedef RegularChecker<checkFine, false> FlipChecker;
            FlipChecker fc(3, apc.get_points(), apc.get_chiro());
            return walk_to_root<FlipChecker, true>(initial, fc);
         } else {
            typedef YesChecker FlipChecker;
            FlipChecker fc(apc.get_points(), apc.get_chiro());
            return walk_to_root<FlipChecker, false>(initial, fc);
         }
         */
      }

   public:

      InitialTriangFinder(
         const APCType& apc_in):
            apc(apc_in)
//            checkRegular(CommandlineOptions::check_regular())
         {}

      TriangNode find_root(const TriangNode& triang) const {
         return set_path(triang);
      }

};


#endif
