#ifndef UNWEIGHTED_GRAPH_H
#define UNWEIGHTED_GRAPH_H

#include <list>
#include <vector>
#include <set>
#include <string>
#include <iostream>
//#include <limits>
using namespace std;

#include "Utils.h"

void OutputQuotedString(ofstream &outFile, const char *buf);

// ***************************************************************************
// Buneman graph utilities
// ***************************************************************************
class BGVertex
{
	friend class BunemanGraph;
	friend class BGEdge;
	friend class UnWeightedGraph;
public:
	BGVertex() : id(0), speciesID("") {}
	BGVertex(const string &nm) : name(nm), id(0), speciesID("") {}
	void AddBlock(bool blk) {blocks.push_back(blk); }
	void SetSpeciesID( const string &id ) { speciesID = id; }
	friend ostream& operator << (ostream& out, const BGVertex &v); 
private:
	string name;		// name of vertex, such as "v1"
	int id;				// unique name for node
	string speciesID;  
	vector<bool> blocks;   // false: first block, true: second block
};
typedef vector<BGVertex> LIST_VERTEX;

class BGEdge
{
	friend class BunemanGraph;
	friend class UnWeightedGraph;
public:
	BGEdge() : v1Pos(-1), v2Pos(-1)   {pv1 = pv2 = NULL;}
	BGEdge(string nm) : name(nm), v1Pos(-1), v2Pos(-1) {pv1 = pv2 = NULL;}
	BGEdge(string nm, int v1p, int v2p, LIST_VERTEX &listVerts) : name(nm), v1Pos(v1p), v2Pos(v2p) 
	{
		pv1 = &listVerts[ v1p ]; 
		pv2 = &listVerts[ v2p ]; 
	}

private:
	string name;			// name of edge, such as "s1"
	int v1Pos; 
	int v2Pos; 
	BGVertex *pv1;		// end vertex1 of edge
	BGVertex *pv2;		// end vertex2 of edge
};

// ***************************************************************************
typedef vector<BGEdge> LIST_EDGE;
typedef set<int> INCOMPATIBLE_SET;		// each integer is for indexing
											// into matrix columns
typedef set<int> SPLIT_BLOCK_SET;		
typedef list<INCOMPATIBLE_SET>  INC_CLIQUE_LIST;
//typedef vector<int> SEQUENCE;			// represent sequence of bits


#define NIL_VERTEX     0x7FFFFFFF


// ***************************************************************************
// UnWightedGraph class
// ***************************************************************************
class UnWeightedGraph
{
public:
	UnWeightedGraph() {}
	UnWeightedGraph( LIST_VERTEX& listVerts, LIST_EDGE& listEs ) :listVertices(listVerts),
		listEdges(listEs) {}
	~UnWeightedGraph() {}
	void SetVertices( LIST_VERTEX &verts) {  listVertices = verts;    }
	void SetEdges( LIST_EDGE &edges) {  listEdges = edges;    }
	int GetNumVertices() const { return listVertices.size(); }
	int GetAdjVert( int src, int lastAdj ) ; 
	bool IsConnected(); 
	void OutputGML( const char *fileName); 
	bool IsNeighour(int i, int j); 
	LIST_VERTEX &GetListVerts() { return listVertices;   }

private:
	LIST_VERTEX listVertices;
	LIST_EDGE listEdges;
};






// ***************************************************************************
// UndirectedGraph class
// ***************************************************************************
class GraphVertex
{
public:
    GraphVertex() {value = id = 0; visited = false;}
    GraphVertex(int id1) : visited(false) {id = id1;}
    GraphVertex(int id1, int val) : visited(false) {id = id1; value = val;}
    GraphVertex(const GraphVertex &rhs) {value = rhs.value; id = rhs.id; visited = rhs.visited;}
//  GraphVertex&  operator=(const GraphVertex &rhs) {value = rhs.value; id = rhs.id; visited = rhs.visited; return this;}

    void SetVisited(bool f) { visited = f; }
    bool IsVisited() {return visited;}
    int GetID() {return id;}
    void SetValue(int v) {value = v;}
    int GetValue() {return value;}
    string GetLabel() const {return label;}
    void SetLabel(string lbl) {label = lbl;}

private:
    int value;          // a vertex can have a value
    int id;             // id is unique, when removal no reuse
    bool visited;
    string label;
};

class GraphEdge
{
public:
    GraphEdge() {vid1 = -1; vid2 = -1; value = -1;}
    GraphEdge(int id1, int id2) {vid1 = id1; vid2 = id2;}
    GraphEdge(int id1, int id2, int v) {vid1 = id1; vid2 = id2; value = v;}
    GraphEdge(const GraphEdge &rhs) {vid1 = rhs.vid1; vid2 = rhs.vid2; value = rhs.value; label = rhs.label;}

    void GetVertexIDs(int &v1, int &v2) {v1 = vid1; v2 = vid2;}
    int GetValue() {return value;}
    void SetValue(int v) {value = v;}
    string GetLabel() const {return label;}
    void SetLabel(string lbl) {label = lbl;}

private:
    int vid1;           // id of the vertex #1
    int vid2;           // id of vertex #2
    int value;          // an edge can have a value
    string label;       // label of the edge
};



#if 0
class GraphEdgeIterator
{
public:
    GraphEdgeIterator( );

private:
    int curPos;
};
#endif

typedef int GRAPH_TRAV_POSITION;



// ***************************************************************************
// Graph classes
// ***************************************************************************
// This is a hopefully generic class for directed graph
// we store, at each vertex, the list of 
class GenericGraph
{

public:
    typedef vector<GraphEdge> EDGE_LIST;
    
    GenericGraph();
    virtual ~GenericGraph() {}


    // Basic graph functions
    virtual int AddVertex(int val);
    virtual bool RemoveVertex(int id); 
    virtual bool AddEdge(int vid1, int vid2, int val) = 0;
	int GetNumVertices() const { return vertices.size(); }
    void GetAllNodesIds(std::set<int> &setIds);
	virtual int GetNumEdges() const;
    virtual int GetEdgeNum (int vid);
    virtual GraphEdge *  GetEdgeByIndex( int vid, int index );
    virtual GraphEdge *GetEdge( int vid, int uid ) ;
    virtual bool IsEdge(int vid, int uid) ;
    virtual bool FindVertexByID(int id, GraphVertex& v);
    virtual GraphVertex *FindVertex( int id );
    virtual void SetVertexVisited(int vid,  bool flag );
    virtual bool IsVertexVisited( int vid );
    virtual void SetVertexLabel(int vid, string lbl);
    virtual GraphVertex *GetVertexByLabel( string lbl );
    virtual void SetEdgeLabel(int vid1, int vid2, string lbl);
    void Dump();

protected:

    map<int, GraphVertex> vertices;      // for faster access, use a map, indexed by id
    map<int, EDGE_LIST> adjacencyList;  // Indexed by id of the vertex
    int nextId; 

};


class UndirectedGraph : public GenericGraph
{
//    typedef vector<GraphEdge> EDGE_LIST;
public:
    UndirectedGraph();
    virtual ~UndirectedGraph();

    // Basic graph functions
    bool AddEdge(int vid1, int vid2, int val);
	int GetNumEdges() const;
  
    
    //bool GetFirstEdge (int vid, GraphEdge &e);
    //bool GetNextEdge( int vid, GraphEdge &e );
    
    
    GraphEdge *GetEdge( int vid, int uid ) ;
    int GetFirstNode(GraphVertex &v);     // return -1 when done
    int GetNextNode(GraphVertex &v);      // return id of the node

    // Some traversal utility here, need improvements later
    void InitTraversal();           // Set visited flag to false
    int TraversalFrom( int id, set<int> &listOfCCVertices );   // Start traversal from node's id = id
    int FindUnvisitedNode ( );      // return the id of an unvisited node, if none return -1
    
    // Some basic functions here
    bool IsBipartitie();
	void FindComponents( set< set<int> > &comps );

    // DFS functions
    void InitPrevConfig();
    void DFSSetPrevNode( int u, int uprev );
    int DFSGetPrevNode( int u);
    void DFSSetNextNode(int u, int unext);
    int DFSGetNextNode( int u);
    
    // more algorithms for graph: return two parts with node ids in two
    int GetMaxCut(set<int> &cutPart1, set<int> &cutPart2);

protected:

    //map<int, GraphVertex> vertices;      // for faster access, use a map, indexed by id
    //map<int, EDGE_LIST> adjacencyList;  // Indexed by id of the vertex
    //int nextId; 

    // private member here
private:
    // Mainly used temporiliy for traversal
    map<int,int>                            prevMap;
    map<int,int>                            nextMap;        // not really neccessary, but to make it simple....
    map<int, GraphVertex> :: iterator       itCurrent;
//    GRAPH_TRAV_POSITION                     curpos;
    int                                     *prevArray;
};


// This is a hopefully generic class for directed graph
// we store, at each vertex, the list of 
class DirectedGraph : public GenericGraph
{
public:

    // Basic graph functions
    bool AddEdge(int vid1, int vid2, int val);
    bool IsNodeSink( int vid );
    bool IsNodeSource( int vid );
    bool IsAcyclic( ) ;
    void TopologicalSort(vector<int> &listNodesIds);

    // Output
	void OutputGML( const char *fileName); 
	void TrimTreeArcs();	// recursivly remove all nodes as sinks


private:

	void DFSVisitAcyclic(int nid, int &time, map<int,int> &nodesColor, map<int,int> &nodesdval, map<int,int> &nodesfval, vector<int> *plistFinishedNodes = NULL );


};




#endif //UNWEIGHTED_GRAPH_H
