#ifndef EBLOCKARRAY_DEC_H
#define EBLOCKARRAY_DEC_H

#include "eutils.h"

#include<vector>
#include<iostream>

using namespace std;

#include "ebasicarray_dec.h"

template <class T>
class eblockarray
{
 private:
  long int blocksize;
  long int count;
 public:
  ebasicarray<T*> blocks;


  class iter : public std::iterator<std::random_access_iterator_tag, T>{
   private:
    long p;
    eblockarray<T>* ba;
   
//    T* m_pter;
   public:
    iter():  p(0),ba(0x00){}
    iter(eblockarray<T>::iter* _i):  p(_i->p),ba(_i->ba){}
    iter(eblockarray<T>* _ba,long _p):  p(_p),ba(_ba){}
    iter(const iter& other_it): p(other_it.p),ba(other_it.ba){}
    iter operator++(int) { iter niter(*this); ++p; return(niter); }
    iter& operator+=(long i) { p+=i; return(*this); }
    iter& operator++() { ++p; return(*this); }
    iter& operator--() { --p; return(*this); }
    iter operator+(long i) const { iter niter(*this); niter.p+=i; return(niter); }
    iter operator-(long i) const { iter niter(*this); niter.p-=i; return(niter); }
    long operator-(const iter& rhs) const { return(p-rhs.p); }
    bool operator!=(const iter& rhs) const {return(p!=rhs.p);}
    bool operator==(const iter& rhs) const {return(p==rhs.p);}
    bool operator<(const iter& rhs) const {return(p<rhs.p);}
    bool operator<=(const iter& rhs) const {return(p<=rhs.p);}
    bool operator>=(const iter& rhs) const {return(p>=rhs.p);}
    bool operator>(const iter& rhs) const {return(p>rhs.p);}
    T& operator*() {return((*ba)[p]); }
  };


  eblockarray();
  eblockarray(const eblockarray<T>& ba);
  ~eblockarray();

  eblockarray<T>& operator=(const eblockarray<T>& ba);

  void clear();

  void add(const T& sdist);
  inline long int size() const { return(count); }

  void reservep(size_t s);
  void swap(long int i,long int j);
  void sort();

  T& operator[](long int i);
  const T& operator[](long int i) const;
  eblockarray<T>& merge(eblockarray& barr);
  inline eblockarray<T>& operator+=(eblockarray& barr){ merge(barr); return(*this); }

  inline iter begin() { return(iter(this,0)); }
  inline iter end() { return(iter(this,size())); }
  inline T* lastblock() { return(blocks[blocks.size()-1]); }
  inline const T* lastblock() const { return(blocks[blocks.size()-1]); }
};

template <class T>
ostream &operator<<(ostream &stream,const eblockarray<T> &var);

#endif

