/* Copyright (c) 2018 -- 2022
   Charles Jordan (Hokkaido University, Sapporo, Japan),
   Michael Joswig, Lars Kastner (Technische Universitaet Berlin, Germany)

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
-----------------------------------------------------------------------------
*/

#ifndef FLIP_CHECKER_HH
#define FLIP_CHECKER_HH

#include "RegularityCheckCache.hh"
#include "CommandlineOptions.hh"


template<typename APCType>
class YesChecker {
   public:
      typedef std::false_type checkRegular;
      typedef std::false_type checkFine;
      typedef std::false_type checkCentral;
      typedef YesChecker Initial;
      
      YesChecker(const APCType& apc_in){}

      bool isValid(const TriangNode& source, const gkz_vector_type& flip_gkz, const std::unordered_map<Flip, FlipInfo>& all_flips, const Flip& flip) const {
         return true;
      }

      bool isGoodNode(const TriangNode& triang) const{
         return false;
      }

      std::string get_extra_data(const TriangNode& triang) const {
         return "";
      }
};

template<typename APCType, typename keepFirstFixed>
class NonRegularChecker {

   public:
      using checkFine = typename APCType::checkFineBool;
      using checkCentral = keepFirstFixed;
      typedef std::false_type checkRegular;
      typedef NonRegularChecker<APCType, std::false_type> Initial;
      
      NonRegularChecker(const APCType& apc_in){}

      bool isValid(const TriangNode& source, const gkz_vector_type& flip_gkz, const std::unordered_map<Flip, FlipInfo>& all_flips, const Flip& flip) const {
         return true;
      }
      
      bool isGoodNode(const TriangNode& triang) const{
         if(checkFine::value){
            if(!isFine(triang)){ return false;}
         }
         return true;
      }

      std::string get_extra_data(const TriangNode& triang) const {
         return "";
      }

};


template<typename APCType, typename keepFirstFixed>
class RegularChecker {

   private:
      const RegularityCheckCache rcc;

   public:
      using checkFine = typename APCType::checkFineBool;
      using checkCentral = keepFirstFixed;
      typedef std::true_type checkRegular;
      typedef RegularChecker<APCType, std::false_type> Initial;
      
      RegularChecker(const APCType& apc):
         rcc(CommandlineOptions::regularity_cache_size(), apc.get_points(), apc.get_chiro(), CommandlineOptions::polymake_lp_client(), apc.get_gkz())
         {}
      
      RegularChecker(const Int n, const PointConfiguration& points, const Chirotope& chiro):
         rcc(n, points, chiro, CommandlineOptions::polymake_lp_client())
         {}

      bool isValid(const TriangNode& source, const gkz_vector_type& flip_gkz, const std::unordered_map<Flip, FlipInfo>& all_flips, const Flip& flip) const {
         return rcc.isRegular(source, flip_gkz, all_flips, flip);
      }
      
      bool isGoodNode(const TriangNode& triang) const{
         if(checkFine::value){
            if(!isFine(triang)){ return false;}
         }
         return rcc.isRegular(triang);
      }

      std::string get_extra_data(const TriangNode& triang) const {
         return rcc.get_secondary_cone_rays(triang);
      }
}; 

#endif


