#include "SphierStruct.h"

using namespace std;


/*Sphier struct*/
SphierStruct::SphierStruct():
   node0Array(),
   node1Array(),
   staticLayer(0),
   ID0(0),
   ID1(0)
   {}

/*Another constructir for SphierStruct*/
SphierStruct::SphierStruct(int rows, int cols):
    node0Array(rows,0),
    node1Array(cols,0),
	staticLayer(0),
	ID0(0),
	ID1(0)
	{}
/*Destructor*/
SphierStruct::~SphierStruct()
{
	//node0Array.~Array();
	//node1Array.~Array();
	//delete node0Array;
	//delete node1Array;
}

/*Add a node*/
void SphierStruct::addNode(Node& node)
{
       table[node.layerNum][node.ID]= node.position;//.insert(pair<int,int>(node.ID,node.position));
	if(node.layerNum == 0){
		node0Array.add(node);
		//ID0 = ID0+1;
	}
	if(node.layerNum == 1){
		node1Array.add(node);
		//ID1 = ID1+1;
	}
}
Node* SphierStruct::findNode(Node* node)
{
	if(node->layerNum == 0)
		return &node0Array[node->ID];
	if(node->layerNum == 1)
		return &node1Array[node->ID];
	
}

Node* SphierStruct::findNode(int ID, int layer)
{
	Node* node = new Node(ID, layer);
        Node* temp = findNode(node);
        if(temp->ID != ID) cout<<"Warning: ID of the extracted node dont match with the given ID"<<endl;
	return temp;
}

void SphierStruct::addNode(std::string name, int Layer){
	
	//Node temp(ID, Layer, name);
	if (Layer == 0){
		Node temp(ID0, Layer, name);
		ID0 = ID0+1;
		addNode(temp);
	}
	if(Layer == 1){
		Node temp(ID1, Layer, name);
		ID1 = ID1+1;
		addNode(temp);
		
	}
	
}
/*set the static layer*/
int SphierStruct::invertStaticLayer()
{
	int result = staticLayer;
    staticLayer = 1-staticLayer;
	return result;
}
void SphierStruct::setPositionBary(int layer)
{
	if(layer == 0){
		int length = node0Array.Length();
		for(int i=0; i< length; i++){
			node0Array[i].setPositionBary();
			table[0][node0Array[i].ID]= node0Array[i].position;
		}
	}
	if(layer == 1){
		int length = node1Array.Length();
		for(int i=0; i< length; i++){
			node1Array[i].setPositionBary();
			table[1][node1Array[i].ID]= node1Array[i].position;
		}
	}
}
void SphierSruct::adjustNodePositions(int layer)
{
  Array<Node>* ptr;
  multimap<int,int> rev;
  if(layer == 0) ptr = &node0Array;
  if(layer == 1) ptr = &node1Array;
  for(int i=0; i< ptr->Length(); i++){
      Node* temp = ptr[i];
      rev.insert(pair<int,int>(temp->position,temp->ID);
      
  }
}

/*Barycenter heuristic based crossing minimization*/
void SphierStruct::setPositionBary()
{
    setPositionBary(invertStaticLayer());	
}

/* print the structure*/
void SphierStruct::printStruct()
{
	for(int layer =0; layer < 2; layer++){
		int length;
		if(layer == 0) length=node0Array.Length();
		else length = node1Array.Length();
		cout<<" Length = "<<length;
    	cout<<" Layer = "<<layer;
		cout<<endl;
		for(int i=0; i < length; i++){
			Node* ptr = findNode(i,layer);
			cout<<"Node: = "<<ptr->name;
			cout <<"   Neighbors: ";
			LinkedList<Node> neighbors = ptr->neighbors;
			const ListElement<Node>* finger = neighbors.Head();
			for(int j=0; j<neighbors.size; j++){
				Node n = finger->Datum();
				cout<<n.name<<" "; 
				finger = finger->Next();
			}
			cout<<endl;
		}
		cout<<endl;
	}

}
void SphierStruct::printMatrix()
{
    int rows = node0Array.Length();
    int cols = node1Array.Length();
    int matrix[rows][cols];
    for(int i=0; i<rows;i++){
        for(int j=0; j<cols; j++){
            int x = table[0][i];
            int y = table[1][j];
            if(node0Array[i].hasNeighbor(node1Array[j]))
                matrix[x][y] = 1;
            else
                matrix[x][y]=0;
         } 
    }
    for(int i=0; i<rows; i++ ){
       for(int j=0; j<cols; j++){
           //if(matrix[i][j] != 1) matrix[i][j] =0;
           cout<<matrix[i][j]<<" ";
       }
       cout<<endl;
    }
    cout<<endl;
}

int main(){
   SphierStruct spt(5,5);
   for (int i=0; i< 5; i++){
        string str1(i,'n');    
         string str2(i,'m');
       spt.addNode(str1,0);
       spt.addNode(str2,1);
   } 
   for(int i=0; i< 5; i++){
      Node* temp1 = spt.findNode(i,0);
      Node* temp2 = spt.findNode(i,1);
      Node* temp3 = spt.findNode((i+1)%5,1);
      temp1->addNeighbor(*temp2);
      temp1->addNeighbor(*temp3);
      temp2->addNeighbor(*temp1);
      temp3->addNeighbor(*temp1);
   }
   spt.printStruct();
   for(int i=0; i<3; i++){
      spt.setPositionBary();
   }
   spt.printMatrix();
}
