#ifndef POLYHEDRALFAN_H_INCLUDED
#define POLYHEDRALFAN_H_INCLUDED

#include <set>
#include <map>

#include "polyhedralcone.h"
#include "polynomial.h"
#include "printer.h"

class SymmetryGroup;

typedef set<PolyhedralCone> PolyhedralConeList;

typedef map<int,IntegerVectorList> IncidenceList;

/* A PolyhedralFan is simply a collection of canonicalized PolyhedralCones. It contains no combinatorial information in the sense of a polyhedral complex. */
class PolyhedralFan
{
  int n;
  PolyhedralConeList cones;
 public:
  static class PolyhedralFan bergmanOfPrincipalIdeal(Polynomial const &p);
  static class PolyhedralFan normalFanOfNewtonPolytope(Polynomial const &p);
  static class PolyhedralFan fullSpace(int n);
  static class PolyhedralFan facetsOfCone(PolyhedralCone const &c);
  PolyhedralFan(int ambientDimension);
  void print(class Printer *p)const;
  void printWithIndices(class Printer *p, SymmetryGroup *sym=0)const; //fan must be pure
  int getAmbientDimension()const;
  int getMaxDimension()const;
  int getMinDimension()const;
  friend PolyhedralFan refinement(const PolyhedralFan &a, const PolyhedralFan &b, int cutOffDimension=-1, bool allowASingleConeOfCutOffDimension=false);
  IntegerVectorList getRays(int dim=1);//This can be called for other dimensions than 1. The term "Rays" still makes sense modulo the common linearity space
  IntegerVectorList getRelativeInteriorPoints();
  PolyhedralCone const& highestDimensionalCone(); //returns one of the cones in the fan with highest dimension
  void insert(PolyhedralCone const &c);
  void remove(PolyhedralCone const &c);
  void removeAllExcept(int a); //deletes all except the first a cones
  void removeAllLowerDimensional();
  void makePure();
  bool contains(PolyhedralCone const &c)const;
  PolyhedralFan facetComplex()const;
  PolyhedralFan facetComplexSymmetry(SymmetryGroup const &sym)const;
  IntegerVectorList getRaysInPrintingOrder(SymmetryGroup *sym)const;
  IncidenceList getIncidenceList(SymmetryGroup *sym=0)const;
  bool isEmpty()const;
  bool isRefinementOf(PolyhedralFan const &f)const;

  typedef PolyhedralConeList::const_iterator coneIterator;
  PolyhedralFan::coneIterator conesBegin()const;
  PolyhedralFan::coneIterator conesEnd()const;
};

#endif
