#ifndef REGIOND2LINKED_H
#define REGIOND2LINKED_H

#include <cassert>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

#include <pnlink.h>
#include <typedefs.h>

template< typename Indx >
class regionD2linked
{
public:

  typedef pnlink<Indx> link;
  typedef Indx const Indxc;


  /** A point in the circular list. */
  link * start;

  regionD2linked();

  regionD2linked( Indxc p0, Indxc p1, Indxc n0, Indxc n1 )
    { start = new link(p0,p1,n0,n1); }

  regionD2linked( Indx p0, Indx p1, Indx p2, 
    Indx n0, Indx n1, Indx n2 )
    { start = new link(p0,p1,p2,n0,n1,n2); }
  regionD2linked( Indx p0, Indx p1, Indx p2, Indx p3,
    Indx n0, Indx n1, Indx n2, Indx n3 )
    { start = new link(p0,p1,p2,p3,n0,n1,n2,n3); }
  regionD2linked( Indx p0, Indx p1, Indx p2, Indx p3, Indx p4,
    Indx n0, Indx n1, Indx n2, Indx n3, Indx n4 )
    { start = new link(p0,p1,p2,p3,p4,n0,n1,n2,n3,n4); }
  regionD2linked( Indx p0, Indx p1, Indx p2, Indx p3, Indx p4, Indx p5,
    Indx n0, Indx n1, Indx n2, Indx n3, Indx n4, Indx n5 )
    { start = new link(p0,p1,p2,p3,p4,p5,n0,n1,n2,n3,n4,n5); }
  regionD2linked( Indx p0, Indx p1, Indx p2, Indx p3, Indx p4, Indx p5, Indx p6,
    Indx n0, Indx n1, Indx n2, Indx n3, Indx n4, Indx n5, Indx n6 )
    { start = new link(p0,p1,p2,p3,p4,p5,p6,n0,n1,n2,n3,n4,n5,n6); }
  regionD2linked( Indx p0, Indx p1, Indx p2, Indx p3, Indx p4, Indx p5, Indx p6, Indx p7,
    Indx n0, Indx n1, Indx n2, Indx n3, Indx n4, Indx n5, Indx n6, Indx n7 )
    { start = new link(p0,p1,p2,p3,p4,p5,p6,p7,n0,n1,n2,n3,n4,n5,n6,n7); }

  /** Write this region as vectors. */
  void vec( vector<Indx> & pi, vector<Indx> & ni ) const;  

  /** When writing the string out if true write the 
      size first. */
  static bool writesize;
 
  /** Write the object out. */
  operator string() const;

  /** Is the region constructed? */
  boolc isnull() const
    { return start==0; }

  /** Find the point ptindx and add new link copying its neighbor. */
  boolc add( Indx ptindex, Indx p0 )
    { assert(start!=0); return start->add(ptindex,p0); }

};



  

//---------------------------------------------------------
// Implementation

template< typename Indx >
bool regionD2linked<Indx>::writesize = true;

template< typename Indx >
regionD2linked<Indx>::regionD2linked()
  : start(0) {}


template< typename Indx >
regionD2linked<Indx>::operator string() const
{
  vector<Indx> pi;
  vector<Indx> ni;
  vec(pi,ni);

  string s;
  uint sz = pi.size();
  if (writesize)
  { 
    stringstream ss; 
    ss << sz; 
    s+=ss.str(); 
    s += "  "; 
  }
  for (uint i=0; i<sz; ++i)
  {
    { stringstream ss; ss << pi[i]; s+=ss.str(); }
    s += " ";
  }

  s += "  ";

  for (uint i=0; i<sz; ++i)
  {
    { stringstream ss; ss << ni[i]; s+=ss.str(); }
    s += " ";
  }

  return s;
}

  

template< typename Indx >
void regionD2linked<Indx>::vec
( 
  vector<Indx> & pi, 
  vector<Indx> & ni 
) const
{
  pi.clear();
  ni.clear();

  if (start==0)
    return;

  pi.push_back(start->plink);
  ni.push_back(start->nlink);
  
  link const * current = start->next;
  for ( ; current!=start; current=current->next )
  {
    pi.push_back(current->plink);
    ni.push_back(current->nlink);
  }
}



#endif



