/*	Author: Zain Ajaz
	Supervisor: Dr. Ryan Leduc
	
	Project created in conformity with the requirements 
	for the Degree of Master of Engineering in Software Engineering, 
	Computing and Software Department, 
	McMaster University
	2012 - 2013

*/
#pragma once
#include <deque>
#include <vector>
#include <iostream>
#include "StateInfoStructure.h"
using namespace std;

namespace DESpot
{
	namespace{	
	static short ce_desnum;

	class PendingQueueNode
	{
	public:
		typedef std::vector<short> SrcTuple;
		SrcTuple StateTuple;
		int Level;
		StateInfoNode * StateReference;
		PendingQueueNode():StateTuple(ce_desnum){}
		~PendingQueueNode(){}
	};

class PendingQueue
{
public:
	typedef std::deque<PendingQueueNode*> LinkList;
	typedef std::vector<short> SrcTuple;
private:
	LinkList list;
	long long listcounter;
	int frontIndex;
	int backIndex;
	PendingQueueNode* tail;
	PendingQueueNode* head;
	int block_size;
	PendingQueue(){}

public:
	PendingQueue(short in_DesNum):listcounter(0),frontIndex(0),backIndex(0)
	{	
		ce_desnum=in_DesNum;
		block_size=100000;
		list.clear();
		PendingQueueNode *temp=new PendingQueueNode[block_size];
		list.push_back(temp);
		head=temp;
        tail=temp;
	}
	PendingQueue(short in_DesNum,int in_Size):listcounter(0),frontIndex(0),backIndex(0),block_size(in_Size)
	{	
		ce_desnum=in_DesNum;
		list.clear();
		PendingQueueNode *temp=new PendingQueueNode[block_size];
		list.push_back(temp);
		head=temp;
        tail=temp;
	}

	~PendingQueue()
	{
		if(list.empty()==false)
		{
			PendingQueueNode *temp=list.front();
			delete [] temp;
			list.pop_front();
		}
	}

public:

	void Enque(SrcTuple &tuple,unsigned long level,StateInfoNode * ref)
	{
		for(short i=0;i<ce_desnum;i++)
		{
			tail->StateTuple[i]=tuple[i];
		}
		tail->Level=level;
		tail->StateReference=ref;
		backIndex++;
		listcounter++;

		if(backIndex==block_size)
		{
			backIndex=0;
			PendingQueueNode *temp=new PendingQueueNode[block_size];
			list.push_back(temp);
			tail=temp;
		}
		else
		{
		tail++;
		}
		
	}

	StateInfoNode * Deque(SrcTuple &tuple,unsigned long& level)
	{  
	for(short i=0;i<ce_desnum;i++)
		{
			tuple[i]=head->StateTuple[i];
		}

	level=head->Level;
	StateInfoNode * Ref= head->StateReference;
	frontIndex++;
	listcounter--;

		if(listcounter<0)
		{
			std::cout<<"error";
		}
		if(frontIndex==block_size)
		{
			frontIndex=0;
			PendingQueueNode* temp=list.front();
			list.pop_front();
			delete [] temp;
			if(list.empty()!=true)
			{
				head=list.front();
			}
			
		}
		else
		{
		head++;
		}
	return Ref;
	}
	


	bool isEmpty()
	{
		if(listcounter==0)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	int itemCount()
	{
		return listcounter;
	}
	int blockSize()
	{
		return list.size();
	}


};

}
}

