//
// This header file defines the container class openArrayT<> and
// its associated iterator. This container class represents an open
// array with packed and unpacked dimensions.
//

#ifndef ARRAY_H
#define ARRAY_H

#include "svdpi.h"

namespace DPI_OO {

	template <typename ARRAY_TYPE, typename ELEM_TYPE>
	class arrayT;

	template <typename ARRAY_TYPE, typename ELEM_TYPE>
	class arrayIterT {

	public:

		arrayIterT(arrayT<ARRAY_TYPE, ELEM_TYPE>* arr, int idx)
			: array(arr),
			  index(idx)
		{}

		~arrayIterT() {}

		arrayIterT<ARRAY_TYPE, ELEM_TYPE>&
		operator = (const arrayIterT<ARRAY_TYPE, ELEM_TYPE>& other)
		{
			index = other->get_index();
			array = other->get_array();
		}

		arrayIterT<ARRAY_TYPE, ELEM_TYPE>&
		operator + (int plus_val)
		{
			index += plus_val;
			return *this;
		}

		arrayIterT<ARRAY_TYPE, ELEM_TYPE>&
		operator ++ ()
		{
			index ++;
			return *this;
		}

		arrayIterT<ARRAY_TYPE, ELEM_TYPE>&
		operator ++ (int)
		{
			index ++;
			return *this;
		}

		ELEM_TYPE* operator * ()
		{
			return array->operator[] (index);
		}

		bool operator != (const arrayIterT<ARRAY_TYPE, ELEM_TYPE>& other)
		{
			if (this->get_array() != other.get_array() ||
				this->get_index() != other.get_index()) {
				return true;
			}
			return false;
		}

		arrayT<ARRAY_TYPE, ELEM_TYPE>* get_array() const { return array; }
		int get_index() const { return index; }

	private:
		arrayT<ARRAY_TYPE, ELEM_TYPE>* array;
		int index;
	};



	template <typename ARRAY_TYPE, typename ELEM_TYPE>
	class arrayT {

	public:
		arrayT();

		arrayT(const arrayT<ARRAY_TYPE, ELEM_TYPE>& from);

		~arrayT();


		// Bit select read and write 
		virtual void getElemVal(int idx, ELEM_TYPE* val) = 0;
		virtual void setElemVal(int idx, const ELEM_TYPE* val) = 0;

		virtual ELEM_TYPE* operator [] (int idx) = 0;

		virtual ARRAY_TYPE* operator* () = 0;
	};

};

#endif
