/* 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.
-----------------------------------------------------------------------------
*/

#include "CommandlineOptions.hh"
#include "ComputeTriangs.hh"
#include "PointConfiguration.hh"
#include "Symmetry.hh"
#include "Chirotope.hh"
#include "mptopcom_typedefs.hh"
#include "SymmetryBlackBox.hh"
#include "helpers.hh"

template<typename OptimizerClass>
void print_optimal(SimplicialComplex& seed, const GroupDecomposer& gd, const gkz_type& gkz, const PointConfiguration& points){
   TriangNode t(0, points.no(), points.rank(), seed), result;
   gkz_vector_type result_gkz(gkz.evaluate(t));
   Symmetry perm(array2symmetry(gd.get_identity()));
   OptimizerClass Optimizer(t, result_gkz, gd, gkz);
   
   result = Optimizer.get_optimal();
   result_gkz = Optimizer.get_optimal_gkz();
   perm = Optimizer.get_permutation();
   std::cout << result;
   std::cout << " - gkz: " << pmVector2string(result_gkz);
   std::cout << " - perm: " << perm;
   std::cout << std::endl;
   
   if(seed.read(std::cin)){
      print_optimal<OptimizerClass>(seed, gd, gkz, points);
   }
}

int main(const int argc, const char** argv) {
   CommandlineOptions::init(argc, argv);
   
   PointConfiguration points;
   if(!points.read(std::cin)){
      std::cerr << "Error while reading point configuration." << std::endl;
      return 1;
   }
   
   SymmetryGroup group(points.no());
   if(!group.read(std::cin)){
      std::cerr << "Error while reading symmetry group." << std::endl;
      return 1;
   }
   
   SimplicialComplex seed;
   if(!seed.read(std::cin)){
      std::cerr << "No triangulation provided." << std::endl;
      return 1;
   }
   
   gkz_type gkz(points);
   GroupDecomposer gd(group, gkz);
   
   bool sg = CommandlineOptions::small_group();
   bool lexMinimal = CommandlineOptions::lex_min();


   if(lexMinimal) {
      if(sg) {
         print_optimal<FullOrbitTriangulationOptimizer<true, std::true_type, std::false_type>>(seed, gd, gkz, points);
      } else {
         print_optimal<TriangulationOptimizer<true, std::true_type>>(seed, gd, gkz, points);
      }
   } else {
      if(sg) {
         print_optimal<FullOrbitTriangulationOptimizer<true, std::false_type, std::false_type>>(seed, gd, gkz, points);
      } else {
         print_optimal<TriangulationOptimizer<true, std::false_type>>(seed, gd, gkz, points);
      }
   }

   
   return 0;
}

