//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef __PLANAR_CANONICAL_ORDERING_HPP__
#define __PLANAR_CANONICAL_ORDERING_HPP__

#include <vector>
#include <list>
#include <boost/config.hpp>
#include <boost/utility.hpp>  //for next and prior
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>


namespace boost
{


  namespace detail {
    enum planar_canonical_ordering_state
         {PCO_PROCESSED, 
          PCO_UNPROCESSED, 
          PCO_ONE_NEIGHBOR_PROCESSED, 
          PCO_READY_TO_BE_PROCESSED};
  }
    
  template<typename Graph, 
           typename PlanarEmbedding, 
           typename OutputIterator, 
           typename VertexIndexMap>
  void planar_canonical_ordering(const Graph& g, 
                                 PlanarEmbedding embedding, 
                                 OutputIterator ordering, 
                                 VertexIndexMap vm)
  {
    
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef typename graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
    typedef typename graph_traits<Graph>::adjacency_iterator
      adjacency_iterator_t;
    typedef typename std::pair<vertex_t, vertex_t> vertex_pair_t;
    typedef typename property_traits<PlanarEmbedding>::value_type 
      embedding_value_t;
    typedef typename embedding_value_t::const_iterator embedding_iterator_t;
    typedef iterator_property_map
      <typename std::vector<vertex_t>::iterator, VertexIndexMap> 
      vertex_to_vertex_map_t;
    typedef iterator_property_map
      <typename std::vector<std::size_t>::iterator, VertexIndexMap> 
      vertex_to_size_t_map_t;
    
    std::vector<vertex_t> processed_neighbor_vector(num_vertices(g));
    vertex_to_vertex_map_t processed_neighbor
      (processed_neighbor_vector.begin(), vm);

    std::vector<std::size_t> status_vector(num_vertices(g), detail::PCO_UNPROCESSED);
    vertex_to_size_t_map_t status(status_vector.begin(), vm);

    std::list<vertex_t> ready_to_be_processed;
    
    vertex_t first_vertex = *vertices(g).first;
    vertex_t second_vertex;
    adjacency_iterator_t ai, ai_end;
    for(tie(ai,ai_end) = adjacent_vertices(first_vertex,g); ai != ai_end; ++ai)
      {
        if (*ai == first_vertex)
          continue;
        second_vertex = *ai;
        break;
      }

    ready_to_be_processed.push_back(first_vertex);
    status[first_vertex] = detail::PCO_READY_TO_BE_PROCESSED;
    ready_to_be_processed.push_back(second_vertex);
    status[second_vertex] = detail::PCO_READY_TO_BE_PROCESSED;

    while(!ready_to_be_processed.empty())
      {
        vertex_t u = ready_to_be_processed.front();
        ready_to_be_processed.pop_front();

        if (status[u] != detail::PCO_READY_TO_BE_PROCESSED && u != second_vertex)
          continue;

        embedding_iterator_t ei, ei_start, ei_end;
        embedding_iterator_t next_edge_itr, prior_edge_itr;

        ei_start = embedding[u].begin();
        ei_end = embedding[u].end();
        prior_edge_itr = prior(ei_end);
        while(source(*prior_edge_itr, g) == target(*prior_edge_itr,g))
          prior_edge_itr = prior(prior_edge_itr);

        for(ei = ei_start; ei != ei_end; ++ei)
          {
            
            edge_t e(*ei); // e = (u,v)
            next_edge_itr = boost::next(ei) == ei_end ? ei_start : boost::next(ei);
            vertex_t v = source(e,g) == u ? target(e,g) : source(e,g);

            vertex_t prior_vertex = source(*prior_edge_itr, g) == u ? 
              target(*prior_edge_itr, g) : source(*prior_edge_itr, g);
            vertex_t next_vertex = source(*next_edge_itr, g) == u ? 
              target(*next_edge_itr, g) : source(*next_edge_itr, g);

            // Need prior_vertex, u, v, and next_vertex to all be
            // distinct. This is possible, since the input graph is
            // triangulated. It'll be true all the time in a simple
            // graph, but loops and parallel edges cause some complications.
            if (prior_vertex == v || prior_vertex == u)
              {
                prior_edge_itr = ei;
                continue;
              }

            //Skip any self-loops
            if (u == v)
                continue;
                                                                
            // Move next_edge_itr (and next_vertex) forwards
            // past any loops or parallel edges
            while (next_vertex == v || next_vertex == u)
              {
                next_edge_itr = boost::next(next_edge_itr) == ei_end ?
                  ei_start : boost::next(next_edge_itr);
                next_vertex = source(*next_edge_itr, g) == u ? 
                  target(*next_edge_itr, g) : source(*next_edge_itr, g);
              }


            if (status[v] == detail::PCO_UNPROCESSED)
              {
                status[v] = detail::PCO_ONE_NEIGHBOR_PROCESSED;
                processed_neighbor[v] = u;
              }
            else if (status[v] == detail::PCO_ONE_NEIGHBOR_PROCESSED)
              {
                vertex_t x = processed_neighbor[v];
                //are edges (v,u) and (v,x) adjacent in the planar
                //embedding? if so, set status[v] = 1. otherwise, set
                //status[v] = 2.

                if ((next_vertex == x &&
                     !(first_vertex == u && second_vertex == x)
                     )
                    ||
                    (prior_vertex == x &&
                     !(first_vertex == x && second_vertex == u)
                     )
                    )
                  {
                    status[v] = detail::PCO_READY_TO_BE_PROCESSED;
                  }
                else
                  {
                    status[v] = detail::PCO_READY_TO_BE_PROCESSED + 1;
                  }                                                        
              }
            else if (status[v] > detail::PCO_ONE_NEIGHBOR_PROCESSED)
              {
                //check the two edges before and after (v,u) in the planar
                //embedding, and update status[v] accordingly

                bool processed_before = false;
                if (status[prior_vertex] == detail::PCO_PROCESSED)
                  processed_before = true;

                bool processed_after = false;
                if (status[next_vertex] == detail::PCO_PROCESSED)
                  processed_after = true;

                if (!processed_before && !processed_after)
                    ++status[v];

                else if (processed_before && processed_after)
                    --status[v];

              }

            if (status[v] == detail::PCO_READY_TO_BE_PROCESSED)
              ready_to_be_processed.push_back(v);

            prior_edge_itr = ei;

          }

        status[u] = detail::PCO_PROCESSED;
        *ordering = u;
        ++ordering;
        
      }
    
  }


  template<typename Graph, typename PlanarEmbedding, typename OutputIterator>
  void planar_canonical_ordering(const Graph& g, 
                                 PlanarEmbedding embedding, 
                                 OutputIterator ordering
                                 )
  {
    planar_canonical_ordering(g, embedding, ordering, get(vertex_index,g));
  }
 

} //namespace boost

#endif //__PLANAR_CANONICAL_ORDERING_HPP__
