/* Copyright (c) 2018
   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 FLIPDATACYCLIC_HH
#define FLIPDATACYCLIC_HH
#include "FlipData_core.hh"




template<typename FlipChecker, typename APCType>
class FlipDataCyclic { 
   
   using pmFlipContainer = typename APCType::pmFlipContainer;

   private:
      
      const APCType&    apc;
      TriangNode source_triang;
      pmFlipContainer upflips, downflips;
      const FlipChecker& fc;

      // Mutation constructor
      FlipDataCyclic(
            const APCType& apc_in,
            TriangNode triang,
            const pmFlipContainer& uf,
            const pmFlipContainer& df,
            const FlipChecker& fc_in
            ): apc(apc_in), upflips(uf), downflips(df), source_triang(triang), fc(fc_in)
         {}


   public:
      typedef FlipDataCyclic<typename FlipChecker::Initial, APCType> Initial;
      typedef FlipChecker Checker;
      
      FlipDataCyclic(
            const APCType& apc_in,
            TriangNode triang,
            const FlipChecker& fc_in
            ): apc(apc_in), source_triang(triang), fc(fc_in)
         {
            this->apc.populate_flips(this->source_triang, this->upflips, this->downflips);
         }
      

      void mutate(const Flip& flip){
         this->source_triang = TriangNode(0, this->source_triang, flip);
         apc.mutate(flip, source_triang, this->upflips, this->downflips);
      }

      FlipDataCyclic mutate(const Flip& flip, const TriangNode& target){
         FlipDataCyclic result(this->apc, target, this->upflips, this->downflips, this->fc);
         apc.mutate(flip, target, result.upflips, result.downflips);
         return result;
      }

      const pmFlipContainer& get_upflips() const{
         return upflips;
      }

      const pmFlipContainer& get_downflips() const{
         return downflips;
      }

};


#endif
