#include <iostream>
#include <cstdlib>

using namespace std;

template <typename ElementType>
Array<ElementType>::Array(long size /* = 10 */, long start /* = 0 */)
   : arr(new ElementType [size]), allocated(size), they_think(size),
     min_idx(start)
{
   if (arr == NULL)
   {
      allocated = they_think = 0;
      min_idx = 0;
   }
}

template <typename ElementType>
Array<ElementType>::Array(const Array<ElementType> & array)
   : arr(new ElementType [array.they_think]), allocated(array.they_think),
     they_think(array.they_think), min_idx(array.min_idx)
{
   if (arr != NULL)
   {
      for (long i = 0; i < they_think; i++)
      {
         arr[i] = array.arr[i];
      }
   }
   else
   {
      allocated = they_think = 0;
      min_idx = 0;
   }
}

template <typename ElementType>
Array<ElementType>::~Array()
{
   delete [] arr;
   arr = NULL;
   allocated = they_think = 0;
   min_idx = 0;
}

template <typename ElementType>
Array<ElementType> & Array<ElementType>::
   operator = (const Array<ElementType> & array)
{
   if (this != &array)
   {
      resize(array.they_think);
      realign(array.min_idx);
      for (long i = 0; i < they_think; i++)
      {
         arr[i] = array.arr[i];
      }
   }
   return *this;
}

template <typename ElementType>
long Array<ElementType>::get_start(void) const
{
   return min_idx;
}

template <typename ElementType>
long Array<ElementType>::get_end(void) const
{
   return min_idx+they_think-1;
}

template <typename ElementType>
long Array<ElementType>::get_size(void) const
{
   return they_think;
}

template <typename ElementType>
void Array<ElementType>::resize(long size)
{
   long i;
   ElementType *narr;
   if (size > allocated)
   {
      if ((narr = new ElementType [size]) != NULL)
      {
         for (i = 0; i < they_think; i++)
         {
            narr[i] = arr[i];
         }
         allocated = size;
         delete [] arr;
         arr = narr;
         they_think = size;
      }
      else
      {
         cerr << "Unable to resize array!" << endl
              << endl
              << "Ignoring attempt..." << endl;
      }
   }
   else
   {
      if (size > they_think)
      {
         they_think = size;
      }
   }
   return;
}

template <typename ElementType>
void Array<ElementType>::realign(long start)
{
   min_idx = start;
   return;
}

template <typename ElementType>
const ElementType & Array<ElementType>::operator [] (long index) const
{
   if ((index >= min_idx) && (index < (min_idx+they_think)))
   {
      return arr[index-min_idx];
   }
   else
   {
      static ElementType crap;
      cout << "Invalid index of " << index
           << " into constant array indexed from "
           << min_idx << " to " << (min_idx+they_think-1) << "!" << endl;
      return crap;
   }
}

template <typename ElementType>
ElementType & Array<ElementType>::operator [] (long index)
{
   if ((index >= min_idx) && (index < (min_idx+they_think)))
   {
      return arr[index-min_idx];
   }
   else
   {
      static ElementType crap;
      cout << "Invalid index of " << index << " into array indexed from "
           << min_idx << " to " << (min_idx+they_think-1) << "!" << endl;
      return crap;
   }
}
