
// JR 	9/27/95
// 	Modified 10/1/95
//	Modified 10/9
//	10/18/95  Modified to use new list class CircList
//		  "switch" members changed.
//	          Tested.
//	10/19/95  Rather nasty shortcoming of CircListIterator::insert
//		  revealed. See replaceDE. Worked around it here,
//		  but modification of CircListIterator deserves consideration.

#ifndef VERTEX_H
#define VERTEX_H

#include "DE.H"
#include "CircList.H"
#include "Set.H"
#include "Boolean.H"

class Vertex: public CircList<DE>
{

 public:
    Vertex():CircList<DE>(){}
    Vertex(const DE& de1)
	: CircList<DE>(de1){}
    Vertex(const DE& de1, const DE& de2)
	: CircList<DE>(de1,de2){}
    Vertex(const DE& de1, const DE& de2, const DE& de3)
	: CircList<DE>(de1,de2,de3){}
    Vertex(const Vertex& v)
	: CircList<DE>(v) {}

    int deleteDE(DE de);
    int deleteDE_name(Name name);

    int replaceDE(DE oldde, const CircList<DE>& newlist);
    int replaceDE(DE oldde, const LinList<DE>& newlist);
    int replaceDE(DE oldde, DE newde);

    Boolean switchWithPredecessor(DE );
    Boolean switchWithSuccessor(DE );

    Boolean isOriginOf(DE ) const;

    Set<Name> nameSetofVertex();

//2002_12_27   friend ostream& operator << ( ostream& out, const CircList<DE>& v);
//2002_12_27   friend istream& operator >> ( istream&  in,       CircList<DE>& v);
};

Set<Name> Vertex::nameSetofVertex()
{
	Set<Name> s;
	CircListBrowser<DE> i(*this);
	for(i.init(); i.ok(); ++i)
		s.add(i.ahead().name());
	return s;
}

int Vertex::deleteDE(DE de)
{
    // Returns number of occurrences deleted.
    int n=0;
    CircListIterator<DE> i(*this);
    for(i.init();i.ok(); )
    {
	if( i.ahead()==de ) {i.deletef();++n;}
      	else ++i;
    }
    assert(n<2);	// A directed edge should appear once or not at all.
    return n;

}

int  Vertex::deleteDE_name(Name de_name)
{
  int n=0;
  DE de1(de_name,1), de0(de_name,0);
  n+=deleteDE(de0);
  n+=deleteDE(de1);
  return n;
}

int Vertex::replaceDE(DE oldde, const CircList<DE>& newlist)
{
  	int n=0;
  	CircListIterator<DE> i(*this);
  	for(i.init();i.ok();)
    	{
      		if(i.ahead()==oldde)
		{
			i.deletef();
//			i.insertb(newlist); 10/19/95 This has unintended
//					    behavior if the oldde is at the
//					    start of the list: the newlist
//					    get inserted at the *tail* of the
//					    list, and therefore itself scanned
//					    as i comes around.
//					    A remedy is to insert forward
//					    and then skip over it:
			i.insertf(newlist);
			int len=newlist.length();
			while(len--) ++i;
// A better solution would be to change CircList inserts to take account
// of whether iterator is atstart or not. If so, an insertb should occur
// behind the iterator, but in front of the list fpointer.
			++n;
		}
		else
		{
			++i;
		}
    	}
	return n;
}

int Vertex::replaceDE(DE oldde, const LinList<DE>& newlist)
{
  	int n=0;
  	CircListIterator<DE> i(*this);
  	for(i.init();i.ok();)
    	{
      		if(i.ahead()==oldde)
		{
			i.deletef();
//			i.insertb(newlist); 10/19/95 This has unintended
//					    behavior if the oldde is at the
//					    start of the list: the newlist
//					    get inserted at the *tail* of the
//					    list, and therefore itself scanned
//					    as i comes around.
//					    A remedy is to insert forward
//					    and then skip over it:
			i.insertf(newlist);
			int len=newlist.length();
			while(len--) ++i;
// A better solution would be to change CircList inserts to take account
// of whether iterator is atstart or not. If so, an insertb should occur
// behind the iterator, but in front of the list fpointer.
			++n;
		}
		else
		{
			++i;
		}
    	}
	return n;
}


int  Vertex::replaceDE(DE oldde, DE newde)
{
  	int n=0;
  	CircListIterator<DE> i(*this);
  	for(i.init();i.ok();++i)
    	{
      		if(i.ahead()==oldde)
		{
			i.replacef(newde);
			++n;
		}
    	}
	return n;
}


Boolean Vertex::switchWithPredecessor(DE e)
{
  	if(rotateToJustBeforeThe(e))
    	{
      		DE ea(popf());
		DE eb(popb());
		pushf(eb);
		pushb(ea);
	      	return 1;
    	}
  	else    return 0;	
}

Boolean Vertex::switchWithSuccessor(DE e)
{
  	if(rotateToJustAfterThe(e))
    	{
      		DE ea(popf());
		DE eb(popb());
		pushf(eb);
		pushb(ea);
	      	return 1;
    	}
  	else    return 0;	
}

Boolean Vertex::isOriginOf(DE de) const
{
	return (occurrencesOf(de)>0);
}


#endif



