#include <iostream>
#include <ctype.h>
#include <assert.h>
#include <set>
#include <unordered_map>

#include "Global.hh"
#include "Field.hh"
#include "Symmetry.hh"
#include "PointConfiguration.hh"
#include "Permutation.hh"
#include "IntegerSet.hh"

int main(const int argc, const char** argv) {
  using namespace topcom;

  if (argc < 2) {
    MessageStreams::forced() << "usage: " << argv[0] << " <dimension>" << std::endl;
    return 1;
  }

  size_type no = atol(argv[1]);

  symmetry_collectordata rowperms;
  
  Permutation sorted(Permutation(no + 1, 1).complement());
  Vector seed(sorted);
  PointConfiguration Permutahedron;
  Permutahedron.augment(seed);

  // travers through all two cycles to generate the entire symmetric group on rows:
  Permutation perm(no, 2);
  do {
    rowperms.insert(Symmetry(perm, true));
  } while (perm.lexnext());
  SymmetryGroup rowsyms(no, rowperms, true);

  // sort symmetries in order to obtain a reproducible result:
  std::set<Symmetry> sorted_symmetries;
  std::copy(rowsyms.begin(), rowsyms.end(), std::inserter<std::set<Symmetry> >(sorted_symmetries, sorted_symmetries.begin()));
  for (std::set<Symmetry>::const_iterator symiter = sorted_symmetries.begin();
       symiter != sorted_symmetries.end();
       ++symiter) {
    Permutahedron.augment(symiter->map(seed));
  }

  symmetry_collectordata rowperm_generators(rowsyms.rowperm_symmetry_generators(Permutahedron));

  SymmetryGroup symmetries(Permutahedron.no(), rowperm_generators);
  
  // print points:
  MessageStreams::result() << Permutahedron << std::endl;
  
  // print symmetry generators sorted in order to
  // obtain a reproducable output:
  symmetries.write_sorted_generators(MessageStreams::result());
  MessageStreams::result() << std::endl;
  return 0;
}

// eof hypersimplex.cc
