//Name: David Yang, Sean McMillan, Dominic Golab
//File: myMatrix.h
//For: CSE 30331: Scrabble Gmae
//12/6/09
/*Description: This file contains the functionality of a matrix. It is a templated Vector of Vector. It can resize and has [] operator functionality, with some exception handling.*/

#include <stdexcept>
#include "myVector.h"

using namespace std;

template<typename T>
class Matrix
{
public:
  Matrix(int numRows=1, int numCols=1, const T& initVal=T()); //constructor
  Vector<T>& operator[](int i);  //overloads bracket operator
  const Vector<T>& operator[](int i) const;  //overloads bracket operator
  int rows() const;  //returns number of rows
  int cols() const;  //returns number of columns
  void resize(int numRows, int numCols);  //resizes the matrix
private:
  int nRows, nCols;  //number of rows and columns
  Vector< Vector<T> > mat; //object of the Vector class
};

//constructor
template<typename T>
Matrix<T>::Matrix(int numRows, int numCols, const T& initVal)
: nRows(numRows), nCols(numCols),
  mat(numRows, Vector<T>(numCols,initVal))
{
}
//overloads bracket operator
template<typename T>
Vector<T>& Matrix<T>::operator[](int i)
{
  //try and catch block to determine whether the address given is invalid. If so, it is changed to 0,0
  try{
  if (i < 0 || nRows <= i){
    i = 0;
    throw out_of_range("Accessing this Matrix address is out of bounds (address changed to 0,0");
    
  }
  }
    catch (out_of_range& oor) {
    cerr << "Out of Range error: " << oor.what() << endl;
  }


  return mat[i];
}

//overloads bracket operator
template<typename T>
const Vector<T>& Matrix<T>::operator[](int i) const
{
  //try and catch block to determine whether the address given is invalid. If so, it is changed to 0,0
  try{
  if (i < 0 || nRows <= i){
    i=0;
    throw out_of_range("Accessing this Matrix address is out of bounds (address returned is 0,0");
  }
  }
  catch (out_of_range& oor) {
    cerr << "Out of Range error: " << oor.what() << endl;
   
}


 
  return mat[i];
}

 //returns number of rows
template<typename T>
int Matrix<T>::rows() const
{
  return nRows;
}

 //returns number of columns
template<typename T>
int Matrix<T>::cols() const
{
  return nCols;
}

//resizes the matrix
template<typename T>
void Matrix<T>::resize(int numRows, int numCols)
{
  //try and catch block to determine if the resize values are negative. if so, resizes to a 1*1 matrix
  try{
	if(numRows < 0 || numCols < 0){

	      numCols=1;
	          numRows=1;
	  throw out_of_range("Error. Improper values entered to resize the matrix. Resized to 1 * 1");
	}
  }
  catch (out_of_range& oor) {

    cerr << "Out of Range error: " << oor.what() << endl;

  }

  mat.resize(numRows);

  for (int i=0; i<numRows; i++)
    mat[i].resize(numCols);

  nRows = numRows;
  nCols = numCols;
}

