/* Copyright (c) 1997-2010
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Darmstadt, Germany)
   http://www.polymake.de

   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 2, 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.
--------------------------------------------------------------------------------
   $Project: polymake $$Id: hypersurface.cc 9991 2010-12-12 23:36:28Z gawrilow $
*/

#include "polymake/client.h"
#include "polymake/Matrix.h"
#include "polymake/IncidenceMatrix.h"
#include "polymake/Rational.h"
#include "polymake/Graph.h"

namespace polymake { namespace tropical {

void hypersurface(perl::Object h)
{
  const Matrix<Rational> monoms=h.give("MONOMIALS");
  const Vector<Rational> coefs=h.give("COEFFICIENTS");

  Matrix<Rational> ineq;

  if (monoms.rows()!=coefs.size())
    throw std::runtime_error("Coefficient vector has the wrong dimension.");

  //construct the lifted polyhedron
  ineq =  (coefs|monoms);
  
  perl::Object p("polytope::Polytope<Rational>");
  p.take("INEQUALITIES") << ineq;
  p.take("BOUNDED") << false;

  const bool pointed=p.give("POINTED");
  if (!pointed) 
    throw std::runtime_error("Hypersurface is not pointed. Not supported yet.");

  const Matrix<Rational> points=p.give("VERTICES");

  const Set<int> far_face=p.give("FAR_FACE");
  const Matrix<Rational> facets=p.give("FACETS");
  const IncidenceMatrix<> vif=p.give("VERTICES_IN_FACETS");
  
  Graph<> dg=p.give("DUAL_GRAPH.ADJACENCY");

  //find the far_face_index
  int i=0;
  for (Entire< Rows< IncidenceMatrix<> > >::const_iterator z=entire(rows(vif)); !z.at_end(); ++z, ++i) {
    if (*z==far_face) {
      dg.out_edges(i).clear(); // deletes the 'cells at infinity'
      break;
    }
  }

  const int n_cells=dg.edges();
  Array< Set<int> > cells(n_cells);
  i=0;
  for (Entire< Edges< Graph<> > >::const_iterator e=entire(edges(dg));  !e.at_end();  ++e, ++i)
        cells[i]=vif.row(e.from_node())*vif.row(e.to_node());

  h.take("POINTS")<<points;
  h.take("RAYS")<<far_face;
  h.take("MAXIMAL_FACES")<<cells;  
}

Function4perl(&hypersurface,"hypersurface(TropicalHypersurface)");

} }

// Local Variables:
// mode:C++
// c-basic-offset:3
// indent-tabs-mode:nil
// End:
