// Prepares the planarity test and the planar embedding
// Parallel edges:  do not need to be ignored, they can be handled
// by the planarity test.
// Selfloops: need to be ignored.
bool PlanarModule::preparation(Graph  &G,bool embed)
{

	if (G.numberOfEdges() < 9 && !embed)
		return true;
	else if (G.numberOfEdges() < 3 && embed)
		return true;


	node v;
	edge e;

	SListPure<node> selfLoops;
	makeLoopFree(G,selfLoops);

	prepareParallelEdges(G);

	int  isolated = 0;
	forall_nodes(v,G)
		if (v->degree() == 0)
			isolated++;

	if (((G.numberOfNodes()-isolated) > 2) &&
		((3*(G.numberOfNodes()-isolated) -6) < (G.numberOfEdges() - m_parallelCount)))
		return false;



	bool planar = true;


	NodeArray<node> tableNodes(G,0);
	EdgeArray<edge> tableEdges(G,0);
	NodeArray<bool> mark(G,0);

	EdgeArray<int> componentID(G);


	// Determine Biconnected Components
	int bcCount = biconnectedComponents(G,componentID);

	// Determine edges per biconnected component
	Array<SList<edge> > blockEdges(0,bcCount-1);
	forall_edges(e,G)
	{
		blockEdges[componentID[e]].pushFront(e);
	} 
//
// Prepare planarity test for one cluster
//
bool CconnectClusterPlanar::preparation(
	Graph  &G,
	cluster &cl,
	node superSink)
{
	int  bcIdSuperSink = -1; // ID of biconnected component that contains superSink
	// Initialization with -1 necessary for assertion
	bool cPlanar = true;


	NodeArray<node> tableNodes(G, nullptr);
	EdgeArray<edge> tableEdges(G, nullptr);
	NodeArray<bool> mark(G, 0);

	EdgeArray<int> componentID(G);


	// Determine Biconnected Components
	int bcCount = biconnectedComponents(G, componentID);

	// Determine edges per biconnected component
	Array<SList<edge> > blockEdges(0, bcCount - 1);
	for (edge e : G.edges) {
		blockEdges[componentID[e]].pushFront(e);
	}

	// Determine nodes per biconnected component.
	Array<SList<node> > blockNodes(0, bcCount - 1);
	for (int i = 0; i < bcCount; i++)
	{
		for (edge e : blockEdges[i])
		{
			if (!mark[e->source()])
			{
				blockNodes[i].pushBack(e->source());
				mark[e->source()] = true;
			}
			if (!mark[e->target()])
			{
				blockNodes[i].pushBack(e->target());
				mark[e->target()] = true;
			}
		}

		if (superSink && mark[superSink]) {
			OGDF_ASSERT(bcIdSuperSink == -1);
			bcIdSuperSink = i;
		}

		for (node v : blockNodes[i]) {
			if (mark[v])
				mark[v] = false;
			else {
				OGDF_ASSERT(mark[v]); // v has been placed two times on the list.
			}
		}
	}

	// Perform planarity test for every biconnected component

	if (bcCount == 1)
	{
		// Compute st-numbering
		NodeArray<int> numbering(G,0);
#ifdef OGDF_DEBUG
		int n =
#endif
		(superSink) ? stNumber(G,numbering,nullptr,superSink) : stNumber(G,numbering);
		OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(G,numbering,n))

		EdgeArray<edge> backTableEdges(G,nullptr);
		for(edge e : G.edges)
			backTableEdges[e] = e;

		cPlanar = doTest(G,numbering,cl,superSink,backTableEdges);
	}
	else
	{
		for (int i = 0; i < bcCount; i++)
		{
			#ifdef OGDF_DEBUG
			if(int(ogdf::debugLevel)>=int(dlHeavyChecks)){
				cout<<endl<<endl<<"-----------------------------------";
				cout<<endl<<endl<<"Component "<<i<<endl;}
			#endif

			Graph C;

			for (node v : blockNodes[i])
			{
				node w = C.newNode();
				tableNodes[v] = w;

#ifdef OGDF_DEBUG
				if (int(ogdf::debugLevel) >= int(dlHeavyChecks)){
					cout << "Original: " << v << " New: " << w << endl;
				}
#endif
			}

			NodeArray<node> backTableNodes(C,nullptr);

			for (edge e : blockEdges[i])
			{
				edge f = C.newEdge(tableNodes[e->source()],tableNodes[e->target()]);
				tableEdges[e] = f;
			}

			EdgeArray<edge> backTableEdges(C,nullptr);
			for (edge e : blockEdges[i])
				backTableEdges[tableEdges[e]] = e;

			// Compute st-numbering
			NodeArray<int> numbering(C,0);
			if (bcIdSuperSink == i) {
#ifdef OGDF_DEBUG
				int n =
#endif
				stNumber(C,numbering,nullptr,tableNodes[superSink]);
				OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(C,numbering,n))
				cPlanar = doTest(C,numbering,cl,tableNodes[superSink],backTableEdges);
			} else {
#ifdef OGDF_DEBUG
				int n =
#endif
				stNumber(C,numbering);
				OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(C,numbering,n))
				cPlanar = doTest(C,numbering,cl,nullptr,backTableEdges);
			}

			if (!cPlanar)
				break;
		}
	}

	return cPlanar;
}