// Copyright (c) 1997-2002  Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Source: /opt/cvs/multisdfDIST/CGAL-3.1/include/CGAL/Nef_S2/SM_io_parser.h,v $
// $Revision: 1.1.1.1 $ $Date: 2010/03/05 22:18:41 $
// $Name:  $
//
// Author(s)     : Michael Seel  <seel@mpi-sb.mpg.de>

#ifndef CGAL_SM_IO_PARSER_H
#define CGAL_SM_IO_PARSER_H

#include <CGAL/Nef_S2/SM_decorator.h>
#include <CGAL/Nef_2/Object_index.h>
#include <CGAL/Nef_S2/SM_decorator_traits.h>
#include <vector>
#include <iostream>

CGAL_BEGIN_NAMESPACE

/*{\Moptions outfile=SM_io_parser.man }*/
/*{\Manpage {SM_io_parser}{Decorator_}{IO of embedded maps}{IO}}*/

/*{\Mdefinition An instance |\Mvar| of the data type |\Mname| is a
decorator to provide input and output of a embedded map.  |\Mtype| is
generic with respect to the |Decorator_| parameter.  |Decorator_| has
to be a decorator model of our |SM_decorator| concept.}*/

/*{\Mgeneralization SM_decorator}*/

template <typename Decorator_>
class SM_io_parser : public Decorator_
{
  typedef Decorator_                         Base;
  typedef typename Decorator_::Sphere_point  Sphere_point;
  typedef typename Decorator_::Sphere_circle Sphere_circle;
  typedef typename Decorator_::Mark          Mark;

  typedef typename Decorator_::Decorator_traits  Decorator_traits;

  typedef typename Decorator_traits::SVertex_iterator     SVertex_iterator;
  typedef typename Decorator_traits::SHalfedge_iterator   SHalfedge_iterator;
  typedef typename Decorator_traits::SFace_iterator       SFace_iterator;
  typedef typename Decorator_traits::SVertex_handle       SVertex_handle;
  typedef typename Decorator_traits::SHalfedge_handle     SHalfedge_handle;
  typedef typename Decorator_traits::SFace_handle         SFace_handle;
  typedef typename Decorator_traits::SHalfloop_handle     SHalfloop_handle;
  typedef typename Decorator_traits::SFace_cycle_iterator SFace_cycle_iterator;
  typedef typename Decorator_traits::SHalfedge_around_svertex_circulator
                                     SHalfedge_around_svertex_circulator;

  std::istream& in; std::ostream& out;
  bool verbose;
  // a reference to the IO object
  CGAL::Object_index<SVertex_handle>   VI;
  CGAL::Object_index<SHalfedge_handle> EI;
  CGAL::Object_index<SFace_handle>     FI;
  std::vector<SVertex_handle>        SVertex_of;
  std::vector<SHalfedge_handle>      Edge_of;
  std::vector<SFace_handle>          SFace_of;
  SHalfloop_handle                   Loop_of[2];
  // object mapping for input
  int vn,en,ln,fn,i;
  // the number of objects

  bool check_sep(char* sep);
  void print_vertex(SVertex_handle) const;
  void print_edge(SHalfedge_handle) const;
  void print_loop(SHalfloop_handle) const;
  void print_face(SFace_handle) const;

  bool read_vertex(SVertex_handle);
  bool read_edge(SHalfedge_handle);
  bool read_loop(SHalfloop_handle);
  bool read_face(SFace_handle);

  void debug_vertex(SVertex_handle) const;
  void debug_edge(SHalfedge_handle) const;
  void debug_loop(SHalfloop_handle) const;

public:
/*{\Mcreation 3}*/
SM_io_parser(std::istream& is, const Base& D);
/*{\Mcreate creates an instance |\Mvar| of type |\Mname|
to input |H| from |is|.}*/

SM_io_parser(std::ostream& os, const Base& D);
/*{\Mcreate creates an instance |\Mvar| of type |\Mname|
to output |H| to |os|.}*/

/*{\Moperations 2 3}*/
void print() const;
/*{\Mop prints |H| to |os|.}*/
void read();
/*{\Mop reads |H| from |is|.}*/
void debug() const;
void print_faces() const;

std::string index(SVertex_handle v) const 
{ return VI(v,verbose); }
std::string index(SHalfedge_handle e) const 
{ return EI(e,verbose); }
std::string index(SHalfloop_handle l) const 
{ if (verbose)  return (l==this->shalfloop()? "l0" : "l1");
  else return (l==this->shalfloop()? "0" : "1");
}
std::string index(SFace_handle f) const 
{ return FI(f,verbose); }

static void dump(const Decorator_& D, std::ostream& os = std::cerr);
/*{\Mstatic prints the plane map decorated by |D| to |os|.}*/

}; // SM_io_parser<Decorator_>


template <typename Decorator_>
SM_io_parser<Decorator_>::
SM_io_parser(std::istream& iin, const Base& H) :
  Base(H), in(iin), out(std::cout), verbose(0), 
  vn(0), en(0), fn(0), ln(0)
{ this->clear(); }

template <typename Decorator_>
SM_io_parser<Decorator_>::
SM_io_parser(std::ostream& iout, const Base& D) 
  : Base(D), in(std::cin), out(iout), 
  VI(this->svertices_begin(),this->svertices_end(),'v'),
  EI(this->shalfedges_begin(),this->shalfedges_end(),'e'),
  FI(this->sfaces_begin(),this->sfaces_end(),'f'),
  vn(this->number_of_svertices()), 
  en(this->number_of_shalfedges()), 
  ln(this->number_of_shalfloops()),
  fn(this->number_of_sfaces())
{ verbose = (out.iword(CGAL::IO::mode) != CGAL::IO::ASCII &&
             out.iword(CGAL::IO::mode) != CGAL::IO::BINARY);
}


//-----------------------------------------------------------------------------
// OUTPUT AND INPUT:
//-----------------------------------------------------------------------------

template <typename Decorator_>
bool SM_io_parser<Decorator_>::check_sep(char* sep)
{
  char c; 
  do in.get(c); while (isspace(c));
  while (*sep != '\0') { 
    if (*sep != c) {
      in.putback(c);
      return false;
    }
    ++sep; in.get(c);
  }
  in.putback(c);
  return true;  
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::print_vertex(SVertex_handle v) const
{
  // syntax: index { isolated incident_object, mark, point }
  out << index(v) << " { ";
  if ( is_isolated(v) ) out << "1 " << index(face(v));
  else                  out << "0 " << index(first_out_edge(v));
  out  << ", " << mark(v) << ", " << point(v) <<  "}\n";
}

template <typename Decorator_>
bool SM_io_parser<Decorator_>::read_vertex(SVertex_handle v)
{ 
  // precondition: nodes exist
  // syntax: index { isolated incident_object, mark, point}
  int n; bool iso; int f; Mark m; Sphere_point p; 
  if ( !(in >> n) ||
       !check_sep("{") ||
       !(in >> iso) ||
       !(in >> f) ||
       !check_sep(",") ||
       !(in >> m) ||
       !check_sep(",") ||
       !(in >> p) ||
       !check_sep("}") ) return false;
 
  if (iso) set_face(v,SFace_of[f]);
  else     set_first_out_edge(v,Edge_of[f]);
  mark(v) = m; point(v) = p;
  return true; 
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::print_edge(SHalfedge_handle e) const
{ // syntax: index { twin, prev, next, source, face, mark, circle }
  out << index(e) << " { "
      << index(twin(e)) << ", " 
      << index(previous(e)) << ", " << index(next(e)) << ", "
      << index(source(e)) << ", " << index(face(e)) << ", "
      << mark(e) << ", " << circle(e) << " }\n";
}

template <typename Decorator_>
bool SM_io_parser<Decorator_>::read_edge(SHalfedge_handle e)
{ // syntax: index { twin, prev, next, source, face, mark, circle }
  int n, eo, epr, ene, v, f; bool m; Sphere_circle k;
  if ( !(in >> n) ||
       !check_sep("{") ||
       !(in >> eo) || !check_sep(",") ||
       !(in >> epr) || !check_sep(",") ||
       !(in >> ene) || !check_sep(",") ||
       !(in >> v) || !check_sep(",") ||
       !(in >> f) || !check_sep(",") ||
       !(in >> m) || !check_sep(",") ||
       !(in >> k) || !check_sep("}") )
    return false;
  CGAL_assertion_msg 
     (eo >= 0 && eo < en && epr >= 0 && epr < en && ene >= 0 && ene < en &&
      v >= 0 && v < vn && f >= 0 && f < fn ,
      "wrong index in read_edge");
  
  // precond: features exist!
  CGAL_assertion(EI[twin(e)]);
  set_prev(e,Edge_of[epr]);
  set_next(e,Edge_of[ene]);
  set_source(e,SVertex_of[v]);
  set_face(e,SFace_of[f]);
  mark(e) = m;
  circle(e) = k;
  return true;
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::print_loop(SHalfloop_handle l) const
{ // syntax: index { twin, face, mark, circle }
  out << index(l) << " { "
      << index(twin(l)) << ", " 
      << index(face(l)) << ", "
      << mark(l) << ", " << circle(l) << " }\n";
}

template <typename Decorator_>
bool SM_io_parser<Decorator_>::read_loop(SHalfloop_handle l)
{ // syntax: index { twin, face, mark, circle }
  int n, lo, f; bool m; Sphere_circle k;
  if ( !(in >> n) ||
       !check_sep("{") ||
       !(in >> lo) || !check_sep(",") ||
       !(in >> f) || !check_sep(",") ||
       !(in >> m) || !check_sep(",") ||
       !(in >> k) || !check_sep("}") )
    return false;
  CGAL_assertion_msg(
    (lo >= 0 && lo < 2 && f >= 0 && f < fn),"wrong index in read_edge");
  
  set_face(l,SFace_of[f]);
  mark(l) = m;
  circle(l) = k;
  return true;
}


template <typename Decorator_>
void SM_io_parser<Decorator_>::print_face(SFace_handle f) const
{ // syntax: index { fclist, ivlist, loop, mark }
  out << index(f) << " { "; 
  SFace_cycle_iterator it;
  CGAL_forall_sface_cycles_of(it,f)
    if ( it.is_shalfedge() ) out << index(SHalfedge_handle(it)) << ' ';
  out << ", ";
  CGAL_forall_sface_cycles_of(it,f)
    if ( it.is_svertex() ) out << index(SVertex_handle(it)) << ' ';
  out << ", ";
  CGAL_forall_sface_cycles_of(it,f)
    if ( it.is_shalfloop() ) out << index(SHalfloop_handle(it));
  out << ", " << mark(f) << " }\n";
}

template <typename Decorator_>
bool SM_io_parser<Decorator_>::read_face(SFace_handle f)
{ // syntax: index { fclist, ivlist, loop, mark }
  int n, ei, vi, li; Mark m;
  if ( !(in >> n) || !check_sep("{") ) return false;
  while (in >> ei) { 
    CGAL_assertion_msg(ei >= 0 && ei < en, 
                           "wrong index in face cycle list.");
    store_boundary_object(Edge_of[ei],f);
  } in.clear();
  if (!check_sep(",")) { return false; }
  while (in >> vi) { 
    CGAL_assertion_msg(vi >= 0 && vi < vn, 
                           "wrong index in iso vertex list.");
    store_boundary_object(SVertex_of[vi],f);
  } in.clear();
  if (!check_sep(",")) { return false; }
  while (in >> li) { 
    CGAL_assertion_msg(li >= 0 && li < 2, 
                           "wrong index in iso vertex list.");
    store_boundary_object(Loop_of[li],f);
  } in.clear();
  if (!check_sep(",") || !(in >> m) || !check_sep("}") ) 
    return false;
  mark(f) = m;
  return true;
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::print() const
{
  out << "Sphere_map_2" << std::endl;
  out << "vertices "  << vn << std::endl;
  out << "edges "     << en << std::endl;
  out << "loops "     << ln << std::endl;
  out << "faces "     << fn << std::endl;
  if (verbose) 
    out << "/* index { isolated ? face : edge, mark, point } */" << std::endl;
  SVertex_iterator vit;
  CGAL_forall_svertices(vit,*this) print_vertex(vit);
  if (verbose) 
    out << "/* index { twin, prev, next, source, face, mark, circle } */" 
	<< std::endl;
  SHalfedge_iterator eit;
  CGAL_forall_shalfedges(eit,*this) print_edge(eit);
  if (verbose) 
    out << "/* index { twin, face, mark, circle } */" << std::endl;
  if ( this->has_shalfloop() ) 
  { print_loop(this->shalfloop()); print_loop(twin(this->shalfloop())); }
  if (verbose) 
    out << "/* index { fclist, ivlist, loop, mark } */" << std::endl;
  SFace_iterator fit;
  CGAL_forall_sfaces(fit,*this) print_face(fit);
  out.flush();
  if (verbose) debug();
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::read() 
{
  if ( !check_sep("Plane_map_2") )  
    CGAL_assertion_msg(0,"SM_io_parser::read: no embedded_PM header.");
  if ( !(check_sep("vertices") && (in >> vn)) ) 
    CGAL_assertion_msg(0,"SM_io_parser::read: wrong vertex line.");
  if ( !(check_sep("edges") && (in >> en) && (en%2==0)) )
    CGAL_assertion_msg(0,"SM_io_parser::read: wrong edge line.");
  if ( !(check_sep("loops") && (in >> ln)) )
    CGAL_assertion_msg(0,"SM_io_parser::read: wrong loop line.");
  if ( !(check_sep("faces") && (in >> fn)) )
    CGAL_assertion_msg(0,"SM_io_parser::read: wrong face line.");

  SVertex_of.reserve(vn);
  Edge_of.reserve(en);
  SFace_of.reserve(fn);
  for(i=0; i<vn; i++)  SVertex_of[i] =   this->new_vertex();
  for(i=0; i<en; i++) 
    if (i%2==0) Edge_of[i] = this->new_edge_pair_without_vertices();
    else Edge_of[i] = twin(Edge_of[i-1]);
  for(i=0; i<fn; i++)  SFace_of[i] =     this->new_face();
  if ( ln == 2 ) 
  { Loop_of[0] = this->new_loop(); Loop_of[1] = twin(this->loop()); }

  for(i=0; i<vn; i++) {
    if (!read_vertex(SVertex_of[i]))
      CGAL_assertion_msg(0,"SM_io_parser::read: error in node line");
  }
  for(i=0; i<en; i++) {
    if (!read_edge(Edge_of[i]))
      CGAL_assertion_msg(0,"SM_io_parser::read: error in edge line");
  }
  if ( ln == 2 ) {
    read_loop(Loop_of[0]); read_loop(Loop_of[1]);
  }
  for(i=0; i<fn; i++) {
    if (!read_face(SFace_of[i]))
      CGAL_assertion_msg(0,"SM_io_parser::read: error in face line");
  }
}

//-----------------------------------------------------------------------------
// VERBOSE OUTPUT:
// note that we output the index of the objects which is stored in them
// this is NOT the member index as produced by the forall loops
//-----------------------------------------------------------------------------

template <typename Decorator_>
void SM_io_parser<Decorator_>::debug_vertex(SVertex_handle v) const
{ 
  out << index(v) << "[" << mark(v) << "," << point(v) << "]" << std::endl; 
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::debug_edge(SHalfedge_handle e) const
{ 
  out << index(e)
      << "(" << index(source(e)) << "," << index(target(e)) << ") "
      << index(twin(e)) << " " << index(face(e))
      << " ["<< mark(e) << "," << circle(e) << "] " << std::endl;
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::debug_loop(SHalfloop_handle l) const
{ 
  out << index(l) << " "
      << index(twin(l)) << " " << index(face(l))
      << " ["<< mark(l) << "] " << circle(l) << std::endl;
}


template <typename Decorator_>
void SM_io_parser<Decorator_>::debug() const
{ 
  out << "\nDEBUG Plane_map\n";
  out << "Vertices:  " << this->number_of_svertices() << "\n";
  out << "SHalfedges: " << this->number_of_shalfedges() << "\n";
  out << "Loop:      " << this->number_of_shalfloops() << "\n";
  SVertex_iterator vit; 
  CGAL_forall_svertices(vit,*this) {
    if ( is_isolated(vit) ) continue;
    SHalfedge_around_svertex_circulator hcirc(out_edges(vit)), hend(hcirc);
    debug_vertex(vit);
    CGAL_For_all(hcirc,hend) { out << "  "; debug_edge(hcirc); }
  }
  if ( this->has_shalfloop() ) 
  { debug_loop(this->shalfloop()); debug_loop(twin(this->shalfloop())); }
  out << std::endl;
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::print_faces() const
{ 
  out << "\nFACES\n";
  out << "Vertices:  " << this->number_of_svertices() << "\n";
  out << "SHalfedges: " << this->number_of_shalfedges() << "\n";
  out << "Loop:      " << this->number_of_shalfloops() << "\n";
  SHalfedge_iterator e;
  Unique_hash_map<SHalfedge_iterator,bool> Done(false);
  CGAL_forall_shalfedges(e,*this) {
    if ( Done[e] ) continue;
    typename Base::SHalfedge_around_sface_circulator c(e), ce = c;
    out << "face cycle\n";
    CGAL_For_all(c,ce) 
    { Done[c]=true; out << "  "; debug_vertex(source(c)); }
  }
  if ( this->has_shalfloop() ) 
  { debug_loop(this->shalfloop()); debug_loop(twin(this->shalfloop())); }
  out << std::endl;
}

template <typename Decorator_>
void SM_io_parser<Decorator_>::dump(const Decorator_& D, std::ostream& os)
{ SM_io_parser<Decorator_> Out(os,D);
  Out.print();
  Out.print_faces();
}



CGAL_END_NAMESPACE
#endif //CGAL_SM_IO_PARSER_H

