/*
 * ADAPT2D : a software for automatic mesh adaptation in 2D
 *
 * AUTHOR : Manuel J. Castro Diaz(e-mail:castro@gamba.cie.uma.es)
 * ADAPTED FOR FREEFEM : Prud'homme Christophe (e-mail:prudhomm@ann.jussieu.fr) 
 *
 * this code is public domain
 * 
 * You may copy freely these files and use it for    
 * teaching or research. These or part of these may   
 * not be sold or used for a commercial purpose without
 * our consent
 * 
 * Any problems should be reported to the AUTHOR
 * at the following address : castro@gamba.cie.uma.es
 */


#ifndef _trianguloT1dlist_h
#define _trianguloT1dlist_h

#include <header.hxx>
#include <t_t1.hxx>
#include <m_t0.hxx>

struct Triangulo_T1_dlink {
  Triangulo_T1* t;
  Triangulo_T1_dlink* suc;
  Triangulo_T1_dlink* prev;
  
  Triangulo_T1_dlink () {t=NIL; suc=NIL; prev=NIL;}
  Triangulo_T1_dlink (Triangulo_T1& tr, Triangulo_T1_dlink* ss,Triangulo_T1_dlink* pp)
  {t=&tr;suc=ss;prev=pp;}
  Triangulo_T1_dlink (Triangulo_T1* tr, Triangulo_T1_dlink* ss,Triangulo_T1_dlink* pp) {
    t=tr; suc=ss; prev=pp;} 
  
  void set (Triangulo_T1& tr, Triangulo_T1_dlink* ss, Triangulo_T1_dlink* pp)
  {t=&tr; suc=ss;prev=pp;}
  void set (Triangulo_T1* tr, Triangulo_T1_dlink* ss, Triangulo_T1_dlink* pp) {
    t=tr; suc=ss; prev=pp;} 
  
  Triangulo_T1_dlink* sig() {return suc;}
  Triangulo_T1_dlink* ant() {return prev;}
};

class Triangulo_T1_dlist {
  
  Triangulo_T1_dlink* last;
  Triangulo_T1_dlink* begin;
  friend ostream& operator<<(ostream&, Triangulo_T1_dlist&);
  
public:
  Triangulo_T1_dlist () {last=NIL; begin=NIL;}
  Triangulo_T1_dlist (Triangulo_T1_dlink* r) {last=begin=r;}
  void insert (Triangulo_T1_dlink* r) {//an~ade al principio de la lista.
    if (begin) {
      r->suc=begin;
      begin->prev=r;
      begin=r;
      
    }
    else {
      last=r;
      begin=r;
    }
  }
  void append(Triangulo_T1_dlink* r) {//an~ade al final de la lista.
    if (last) {
      last->suc=r;
      r->prev=last;
      last=r;
    }
    else {
      last=r;
      begin=r;
    }
  }
  void  enlaza (Triangulo_T1_dlist* rll) {  //une this+rll
    if (begin) {
      if (rll->begin) {
        last->suc=rll->begin;
        (rll->begin)->prev=last;
        last=rll->last;
        rll->begin=NIL;
        rll->last=NIL;
      }
    }
    else {
      begin=rll->begin;
      last=rll->last;
      rll->begin=NIL;
      rll->last=NIL;
    }
  }
  void  enlaza (Triangulo_T1_dlist& rll) {  //une this+rll
    if (begin) {
      if (rll.begin) {
        last->suc=rll.begin;
        (rll.begin)->prev=last;
        last=rll.last;
        rll.begin=NIL;
        rll.last=NIL;
      }
    }
    else {
      begin=rll.begin;
      last=rll.last;
      rll.begin=NIL;
      rll.last=NIL;
    }
    
  }
  void kill (Triangulo_T1_dlink* r) { //elimina un elmento de la dlista
    if (r) {
      if (r==begin) {
        begin=r->suc;
        if (begin) begin->prev=NIL;
      }
      else {
        if (r==last) {
          last=r->prev;
          last->suc=NIL;
        }
        else {
          (r->prev)->suc=r->suc;
          (r->suc)->prev=r->prev;
        }
      }
      delete r; r=NIL;
    }
  }
  
  Triangulo_T1_dlink* principio () {return begin;}
  Triangulo_T1_dlink* fin () {return last;}

  int num_elem () {
    int num=0;
    Triangulo_T1_dlink* aux=begin;
    while (aux) {
      num++;
      aux=aux->suc;
    }
    return num;
  } 
  Boolean contiene(Vertice_T1*);
  
  Vertice_T1* suprime(Vertice_T1*,Triangulo_T1[],
                      Mallado_T0*, Metrica ,int, Arista_T1&);
  Boolean  test_suprime(Vertice_T1*, Vertice_T1*, Arista_T1*, int);

  void clear () {
    Triangulo_T1_dlink* aux;
    while (begin) {
      aux=begin->suc;
      delete begin;
      begin=aux;
    }
    last=begin=NIL;
  }                             
  void operator delete (void* p){
    if (p) {
      ((Triangulo_T1_dlist*)p)->clear();
      delete p; p=NIL;
    }
  }
  void write (ostream&);
  void areas();
};
#endif       

