#ifndef STACK_H
#define STACK_H

#include <iostream>

namespace sat_atpg {

template <class T>
class My_Vector
{
	private:
		T *array;
		int size;
		T t_true;
	public:
		My_Vector ( int _size, T _t_true) :size ( _size ),t_true(_t_true)  { array = new T[size]; }
		My_Vector ( T *_array, int _size, T _t_true) : array(_array), size(_size), t_true(_t_true){}		
		int length() { return size;}
                ~My_Vector() { delete []array;}

		T &operator [] ( int index )
		{
			return array[index];
		}

		T operator [] ( int index ) const
		{
			return array[index];
		}

		bool operator == ( const My_Vector<T>& m_v )
		{
			if ( size != m_v.size )
				return false;
			for ( int i=0;i<size;i++ )
				if ( array[i] != m_v.array[i] )
					return false;
			return true;
		}
		bool operator ^ ( const My_Vector<T>& m_v )
		{	
			for(int i=0;i<size;i++ )
			   {		
				if ( t_true == (array[i] ^ m_v.array[i]))
				    return true;
                           }
			return false;
		}
		My_Vector<T>* operator + ( const My_Vector<T>& m_v )
		{
		 T *t= new T[size];
		 for (int i=0; i<size; i++)
                    {
		      t[i]= array[i] + m_v.array[i];
                    } 
		 My_Vector<T> *m = new My_Vector<T>(t,size,t_true);
		return m;	 
		}
       std::ostream& operator << ( std::ostream& os)
{
	for ( int i=0; i<size;i++ )
		os << array[i];
	return os;
}
	
};

/*
template <class T>
std::ostream& operator << ( std::ostream& os,const My_Vector<T>& m_v )
{
	for ( int i=0; i<m_v.length();i++ )
		os << m_v[i];
	return os;
};
*/





/*
template <class T>
class Array
{
private:
	int pocet;
	int maxPocet;
	T* pole;

	Array(const Array<T>& array);
	Array<T>& operator = (const Array<T>& array);

public:
	Array(int nSize=10);
	~Array();

	void Vloz(T prvek);
	T operator [](int index) const
	{
		return pole[index];
	}

	T& operator [](int index)
	{
		return pole[index];
	}

};*/

template <class T>
class My_Element
{
	public:
		T *data;
		My_Element *next;
		My_Element ( T* _data, My_Element* _next ) : data ( _data ), next ( _next ) {}
};

template <class T>
class My_Stack
{
	private:
		My_Element<T>* data;
		My_Element<T>* current; 
		int element_count;
	public:
		My_Stack() :data ( 0 ),current(0),element_count ( 0 ) {}
		~My_Stack();
		void push ( T *p );
		void pop();
		T* top();
		bool is_empty();
		int get_count() {return element_count;};
		T* first();
		T* next();
};

template <class T>
class My_Queue
{
	private:
		My_Element<T> *head,*tail;
		int element_count;
	public:
		My_Queue() :head ( 0 ),tail ( 0 ),element_count ( 0 ) {}
		~My_Queue();
		void push ( T* p );
		void pop();
		void first_to_end();
		T* top();
		bool is_empty();
		int get_count();
};

template <class T>
class My_Array
{
	private:
		int count;
		int max_count;
		T* array;

	public:
		My_Array ( const My_Array<T>& ma );
		My_Array<T>& operator = ( const My_Array<T>& array );
		My_Array ( int _max_count=10 );
		~My_Array();

void remove ( int index )
		{
			if ( index<count )
			{
				count--;
				array[index]=array[count];
			}
		}

		void insert ( T t );
		T operator [] ( int index ) const
		{
			return array[index];
		}

		T& operator [] ( int index )
		{
			return array[index];
		}

		int length() const
		{
			return count;
		}
};

template <class T>
My_Array<T>::My_Array ( int _max_count )
{
	count=0;
	max_count=_max_count;
	array=new T[_max_count];
}

template <class T>
My_Array<T>::My_Array ( const My_Array<T>& ma )
{
	count = ma.count;
	max_count = ma.max_count;
	array = new T[max_count];
	for ( int i=0;i<count;i++ )
		array[i] = ma.array[i];
}

template <class T>
My_Array<T>::~My_Array()
{
	delete[]array;
}

template <class T>
void My_Array<T>::insert ( T t )
{
	if ( count>=max_count )
	{
		T* p=new T[2*max_count];
		memcpy ( p,array,max_count*sizeof ( T ) );
		delete[]array;
		array=p;
		max_count=2*max_count;
	}
	array[count++]=t;
}

template <class T>
std::ostream& operator << ( std::ostream& os,const My_Array<T>& m_a )
{
	for ( int i=0; i<m_a.count;i++ )
		os << m_a.array[i];
	return os;
};



template <class T>
My_Stack<T>::~My_Stack()
{
	while ( !this->is_empty() )
		this->pop();
}

template <class T>
void My_Stack<T>::push ( T* p )
{
	My_Element<T>* e = new My_Element<T> ( p,this->data );
	this->data = e;
	element_count++;
}

template <class T>
void My_Stack<T>::pop()
{
	My_Element<T> *next = this->data->next;
	delete this->data;
	this->data = next;
	element_count--;
}

template <class T>
T* My_Stack<T>::top()
{
	return this->data->data;
}

template <class T>
bool My_Stack<T>::is_empty()
{
	return ( this->data == 0 );
}

template <class T>
T* My_Stack<T>::first()
{
 current = data;
 return current->data;
}	

template <class T>
T* My_Stack<T>::next()
{
 if (current==0)
   return 0;
 current = current->next;
 if (current==0)
   return 0;
 return current->data;
}




template <class T>
My_Queue<T>::~My_Queue()
{
	while ( !this->is_empty() )
		this->pop();
}

template <class T>
void My_Queue<T>::push ( T* p )
{
	My_Element<T>* e = new My_Element<T> ( p,0 );
	if ( this->head == NULL )
		this->head = e;
	else
		this->tail->next = e;
	this->tail = e;

	element_count++;
}

template <class T>
void My_Queue<T>::pop()
{
	My_Element<T>* n = this->head->next;
	if ( head==tail )
		tail=0;
	delete this->head;
	this->head = n;
	element_count--;
}

template <class T>
T* My_Queue<T>::top()
{
	return this->head->data;
}

template <class T>
bool My_Queue<T>::is_empty()
{
	return ( this->head == 0 );
}

template <class T>
int My_Queue<T>::get_count()
{
	return this->element_count;
}

template <class T>
void My_Queue<T>::first_to_end()
{
T *t=top();
pop();
push(t);
/*	this->tail->next = this->head;
	this->tail = this->head;
	this->head = this->head->next;
*/
}
}

#endif
