/* 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 TRIANGULATION_LOGGER_HH
#define TRIANGULATION_LOGGER_HH

#ifdef MTS
void mtstcreturn(const TriangNode& tn);
void put_output(size_type count, const std::string& outputString);
#endif

template<typename TriangulationType, typename Oracle, typename TGType>
class TriangulationLogger {
   private:
      using FlipChecker = typename Oracle::FlipChecker;
      using APCType = typename Oracle::APC;
      const APCType& apc;
      const FlipChecker& fc;
      size_type                       _totalcount;
      TGType                          tree;

      void log_node_callback(const TriangNode& triang) {
#ifdef MTS
         put_output(_totalcount, apc.get_triangulation_data(triang));
#else
         std::cout << _totalcount << ": " << apc.get_triangulation_data(triang) << std::endl;
#endif
         _totalcount++;
      }

   public:
      TriangulationLogger(const Oracle& oracle):
         apc(oracle.get_apc()), fc(oracle.get_fc()), _totalcount(0), tree(apc, fc) {}
      
      void log_node(const TriangulationType& t) {
         log_node_callback(t.get_triang());
      }

      void tree_add_node(const TriangulationType& t) {
         tree.add_node_safely(t.get_triang());
      }

      void tree_add_edge(const TriangulationType& start, const TriangulationType& end) {
         tree.add_edge(start.get_triang(), end.get_triang());
      }

      void exit_node(const TriangulationType& t) const {
#ifdef MTS
         mtstcreturn(t.get_triang());
#endif
      }

      void print_tree(){
         tree.print();
         tree.print_polymake();
      }

      size_type get_totalcount() const {
         return _totalcount;
      }
};

#endif
