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

///////////////////////////////////////////////////////////////////////////////
// File: mptopcom_typedefs.hh
//
// File contains all types that we currently use for mptopcom.
///////////////////////////////////////////////////////////////////////////////

#pragma once

#include "IntegerSet.hh"

#include <polymake/Map.h>
#include <polymake/Vector.h>
#include <polymake/Integer.h>

#include "SimplicialComplex.hh"
#include "Flip.hh"
#include "TriangNode.hh"


// Some typedefs from TOPCOM moved here so we can use them
// typedef size_type integer_key;

template<typename Scalar, typename Vectortype, typename TriangVectortype> class GKZ;
// Global scalar we work with
// typedef pm::Integer Scalar; // works, but slow
typedef Int Scalar;

// GKZ vectors have the following type
typedef pm::Vector<Scalar> gkz_vector_type;
// signature vectors have the following type
typedef pm::Vector<Int> signature_vector_type;
// The vector encoding a triangulation with 0/1 has the following type
typedef pm::Set<Int> triang_vector_type;

// The GKZ object gives us both the gkz vectors and the vector encoding a
// triangulation. It has the following type:
typedef GKZ<Scalar, gkz_vector_type, triang_vector_type>  gkz_type;


struct FlipInfo {
   TriangNode target;
   gkz_vector_type gkz;
   bool isValid, isFine;
   Int isUpflip;
};





// Flips belonging to triangulations are stored in the following way. Polymake
// then takes care of the sorting automatically.
// typedef pm::Map<gkz_vector_type, Flip> pmFlipContainer;
template<typename K, typename V, typename... Params>
using pmFlipHash = pm::Map<K,V,Params...>;




// For using Flips in std::unordered_set and std::set and for iterating over
// IntegerSet we need the following.
namespace std {
   template<>
      struct hash<Flip> {
         std::size_t operator()(const Flip& flip) const {
            std::size_t r1(0);
            for(size_type k=0; k<flip.first.keysize(); ++k){
               r1 ^= flip.first.key(k);
            }
            return r1;
         }
      };

   template <>
      struct iterator_traits< __sc_const_iterator<IntegerSet> > {
         typedef forward_iterator_tag iterator_category;
         typedef IntegerSet value_type;
         typedef void difference_type;
         typedef void pointer;
         typedef void reference;
      };
}
