#ifndef PENDINGLIST_H
#define PENDINGLIST_H


//#define MAX_PENDING_SIZE 100000

#include <deque>
#include <vector>
#include <iostream>
using namespace std;

namespace DESpot
{

class PendingList
{
public:
	typedef std::deque<short*> LinkList;
	typedef std::vector<short> SrcTuple;
private:
	short m_DesNum;
    LinkList list;
	int listcounter;
	int frontIndex;
	int backIndex;
	short* front_block;
	short* back_block;
	int max_pendingsize;

public:
	PendingList(short in_desnum):m_DesNum(in_desnum),listcounter(0),frontIndex(0),backIndex(0)
	{
		max_pendingsize=100000;
		list.clear();
		short *temp=new short[max_pendingsize*m_DesNum];
		list.push_back(temp);
		front_block=temp;
        back_block=temp;
	}
	PendingList(short in_desnum, int in_Size):m_DesNum(in_desnum),listcounter(0),frontIndex(0),backIndex(0),max_pendingsize(in_Size)
	{
		list.clear();
		short *temp=new short[max_pendingsize*m_DesNum];
		list.push_back(temp);
		front_block=temp;
        back_block=temp;
	}



	~PendingList()
	{
		if(list.empty()==false)
		{
			short *temp=list.front();
			delete temp;
			list.pop_front();
		}
	}

public:

	void PushPending(SrcTuple &tuple)
	{
		
		if(backIndex==max_pendingsize)
		{
			backIndex=0;
			short *temp=new short[max_pendingsize*m_DesNum];
			list.push_back(temp);
			back_block=temp;
		}
		for(int i=0;i<(int)m_DesNum;i++)
		{
			back_block[backIndex*m_DesNum+i]=tuple[i];
		}
        backIndex++;
		listcounter++;
	}

	void PopPending(SrcTuple &tuple)
	{  
		for(int i=0;i<(int)m_DesNum;i++)
		{
			tuple[i]=front_block[frontIndex*m_DesNum+i];
		}
		frontIndex++;
		listcounter--;
		if(listcounter<0)
		{
			std::cout<<"error";
		}
		if(frontIndex==max_pendingsize)
		{
			frontIndex=0;
			short *temp=list.front();
			list.pop_front();
			delete temp;
			if(list.empty()!=true)
			{
				front_block=list.front();
			}
			
		}

	}
	


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

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


};









class PendingVector
{

public:
	typedef std::vector<short*> LinkList;
	typedef std::vector<short*>::iterator LinkListIt;
	typedef std::vector<short> SrcTuple;
private:
	short m_DesNum;
    LinkList list;
	
	int listcounter;
	int vectorIndex;
	int frontIndex;
	int backIndex;
	short* front_block;
	short* back_block;
	int max_pendingsize;



public:
	PendingVector(short in_desnum):m_DesNum(in_desnum),listcounter(0),frontIndex(0),backIndex(0)
	{
		max_pendingsize=100000;
		list.clear();
		short *temp=new short[max_pendingsize*m_DesNum];
		list.push_back(temp);
		front_block=temp;
        back_block=temp;
		vectorIndex=0;
	}
	PendingVector(short in_desnum, int in_Size):m_DesNum(in_desnum),listcounter(0),frontIndex(0),backIndex(0),max_pendingsize(in_Size)
	{
		list.clear();
		short *temp=new short[max_pendingsize*m_DesNum];
		list.push_back(temp);
		front_block=temp;
        back_block=temp;
		vectorIndex=0;
	}

	~PendingVector()
	{
		for(LinkListIt it=list.begin();it!=list.end();it++)
		{
		   short *temp=*it;
		   delete temp;
		}
       
	}

public:

	void PushPending(SrcTuple &tuple)
	{
		if(backIndex==max_pendingsize)
		{
			backIndex=0;
			short *temp=new short[max_pendingsize*m_DesNum];
			list.push_back(temp);
			back_block=temp;
		}



		for(int i=0;i<(int)m_DesNum;i++)
		{
			back_block[backIndex*m_DesNum+i]=tuple[i];
		}
        backIndex++;
		listcounter++;
	}

	void PopPending(SrcTuple &tuple)
	{  
		for(int i=0;i<(int)m_DesNum;i++)
		{
			tuple[i]=front_block[frontIndex*m_DesNum+i];
		}
		frontIndex++;
		listcounter--;

		if(frontIndex==max_pendingsize)
		{
			vectorIndex++;
			frontIndex=0;
			if(vectorIndex<(int)list.size())
			{
				front_block=list[vectorIndex];
			}
		    
	
		}

	}
	
	void GetTurple(int id,SrcTuple &tuple)
	{
			int v_index=id/max_pendingsize;
		    int b_index=id%max_pendingsize;
			
			if(v_index<(int)list.size())
			{
				short *cur_block=list[v_index];
		        for(int i=0;i<(int)m_DesNum;i++)
				{
					tuple[i]=cur_block[b_index*m_DesNum+i];
			    }
			}			
	}


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

	int ItemSize()
	{
		return list.size();
	}
};


}

#endif