/* Array1.h  --  Array class for storing arrays of integers */
#include <iostream>
#include <iomanip>
#include <new>               // C++ standard "new" operator
#include <cstdlib>           // exit function prototype
#include "Array1.h"

using namespace std;


// Default constructor for class Array (default size 10)
Array::Array(int arraySize) {
  // validate arraySize
  size = (arraySize > 0 ? arraySize : 10);

  ptr = new int[size];       // create space for array

  for (int i = 0; i < size; i++) {
    ptr[i] = 0;              // initialize array
  }
}



// Copy constructor for class Array
Array::Array(const Array& arrayToCopy) : size(arrayToCopy.size) {
  ptr = new int[size];       // create space for array

  for (int i = 0; i < size; i++) {
    ptr[i] = arrayToCopy.ptr[i];
  }

}



// Destructor for class Array
Array::~Array() {
  delete[] ptr;
}



// Return size of array
int Array::getSize() const {
  return size;
}



// Overloaded assignment operator;
// const return avoids: (a1 = a2) = a3
const Array& Array::operator=(const Array& right) {
  if (&right != this) {      // check for self-assignment
    // For arrays of different sizes, deallocate original
    // left-side array, then allocate new left-side array
    if (size != right.size) {
      delete[] ptr;          // reclaim space
      size = right.size;     // resize this object
      ptr = new int[size];   // create space for array copy
    }

    for (int i = 0; i < size; i++) {
      ptr[i] = right.ptr[i]; // copy array into object
    }
  }
  return *this;              // enables x = y = z, for example
}



// Determine if two arrays are equal and return true,
// otherwise return false
bool Array::operator==(const Array& right) const {
  if (size != right.size) {
    return false;            // arrays of different sizes
  }

  for (int i = 0; i < size; i++) {
    if (ptr[i] != right.ptr[i]) {
      return false;          // arrays are not equal
    }
  }
  return true;               // arrays are equal
}



// Overloaded subscript operator for non-const Arrays
// reference return creates an lvalue
int& Array::operator[](int subscript) {
  // check for subscript out of range error
  if (subscript < 0 || subscript >= size) {
    cout << "\nError: Subscript " << subscript
         << " out of range" << endl;

    exit(1);                 // terminate program; subscript out of range
  }

  return ptr[subscript];     // reference return
}



// Overloaded subscript operator for const Arrays;
// const reference return creates an rvalue
const int& Array::operator[](int subscript) const {
  // check for subscript out of range error
  if (subscript < 0 || subscript >= size) {
    cout << "\nError: Subscript " << subscript
         << " out of range" << endl;

    exit(1);                 // terminate program; subscript out of range
  }

  return ptr[subscript];     // const reference return
}



// Overloaded input operator for class Array;
// inputs values for entire array
istream& operator>>(istream& input, Array& a) {
  for (int i = 0; i < a.size; i++) {
    input >> a.ptr[i];
  }

  return input;              // enables cin >> x >> y;
}



// Overloaded output operator for class Array
ostream& operator<<(ostream& output, const Array& a) {
  int i;

  // output private ptr-based array
  for (i = 0; i < a.size; i++) {
    output << setw(12) << a.ptr[i];
    if ((i + 1) % 4 == 0) {  // 4 numbers per row of output
      output << endl;
    }
  }

  if (i % 4 != 0) {          // end last line of output
    output << endl;
  }

  return output;             // enables cout << x << y;
}
