#ifndef REGIOND2TESS_H
#define REGIOND2TESS_H

#include <regionD2linked.h>

/*!
\brief Tessellation of linked regions.

vi and pts are vectors.

Through the template parameters the client can control
 memory of the vectors, for example Vreg could be a vector
 holding the regions and Vpts a reference to the points.

*/
template
< 
  typename Vreg, 
  typename Vpts, 
  typename Indx = unsigned int 
>
class regionD2tess
{

public:

  /** Vector of region indexes to the points. */
  Vreg vi;
  /** Vector of points. */
  Vpts pts;

  /** A tessellation is composed of regions and points. */
  regionD2tess( Vreg _vi, Vpts _pts)
    : vi(_vi), pts(_pts) {}

  /** Verify the regions are connected. */
  boolc verify() const;

  /** Print out the tessellation to cout. */
  void print() const;

  /** Print out the tessellation with numbering on left side to cout. */
  void printnumbered() const;

};


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

template< typename Vreg, typename Vpts, typename Indx >
void regionD2tess<Vreg,Vpts,Indx>::printnumbered() const
{
  // Preserve and later restore the setting.
  bool writesize = regionD2linked<Indx>::writesize;
  regionD2linked<Indx>::writesize = false;

  Indx const imax = vi.size();
  for (Indx i=0; i<imax; ++i)
  {
    cout << i << "  ";
    regionD2linked<Indx> & reg(vi[i]);
    if (reg.isnull())
    {
      cout << endl;
      continue;
    }

    cout << (string)reg << endl;
  }

  regionD2linked<Indx>::writesize = writesize;
}

template< typename Vreg, typename Vpts, typename Indx >
void regionD2tess<Vreg,Vpts,Indx>::print() const
{
  Indx const imax = vi.size();
  for (Indx i=0; i<imax; ++i)
  {
    regionD2linked<Indx> & reg(vi[i]);
    if (reg.isnull())
      continue;

    cout << (string)reg << endl;
  }
}

template< typename Vreg, typename Vpts, typename Indx >
boolc regionD2tess<Vreg,Vpts,Indx>::verify() const
{
  Indx const imax = vi.size();
  for (Indx i=0; i<imax; ++i)
  {
    regionD2linked<Indx> & reg(vi[i]);
    if (reg.isnull())
      continue;

    pnlinkiter<Indx> k(reg.start);
    for ( k.reset(); !k; ++k )
    {
      if (k->nlink>imax)
        return false;
      if (vi[k->nlink].start->niInverse(i) == 0)
        return false;
    }
  }

  return true;
}




#endif



