/** Array2D - Provides tools for manipulating a 2D array
   
	@author - Nancy Harris
	@version - V1 - 01/30/2012
 */
public class Array2D
{
	/** getTotal sums all of the values of the array.
	 *
	 * @param matrix The two dimensional array
	 * @return The sum of the array elements
	 */
	public static double getTotal(double [][] matrix)
	{
		double total = 0;
		if (matrix != null)
			for (int row = 0; row < matrix.length; row++)
			{
				if (matrix[row] != null)
				{	
					for (int col = 0; col < matrix[row].length; col++)
						total += matrix[row][col];
				}
			}
		else
			throw new NullPointerException();
		
		return total;
	}
	
	/** getaverage averages all of the values of the array.
	 *
	 * @param matrix The two dimensional array
	 * @return The average of the array elements or -1 if 
	 *         there are no elements
	 * @throws NullPointerException if the matrix is null
	 */

	public static double getAverage(double [][] matrix)
	{
		double average;
		double total = getTotal(matrix);
		double count = getCount(matrix);
		if (count > 0)
			average = total / count;
		else
			average = -1;
		return 99999;
	}
	
	/** getRowTotal sums all of the values in one row of the array.
	 *
	 * @param matrix The two dimensional array
	 * @param row The number (0 based) of the row to sum
	 *
	 * @return The sum of the row array elements.  If the row does not exist
	 *         in matrix....YOU FILL IN THE REST.
	 * @throws ArrayIndexOutOfBoundsException when the row does
	 *         not exist
	 */

	public static double getRowTotal(double [][] matrix, int row)
	{
		double total = 0;
		
		if(matrix == null)
			throw new NullPointerException();
				
		if (isRow(matrix, row))
		{
			for (int col = 0; col < matrix[row].length; col++)
			{
					total += matrix[row][col];
			}
		}
		else 
			throw new ArrayIndexOutOfBoundsException("ROW: " + row);
		return total;
	}
	
	/** getColumnTotal sums all of the values in one column of the array.
	 *
	 * @param matrix The two dimensional array
	 * @param col The number (0 based) of the col to sum
	 *
	 * @return The sum of the array elementsin that column.  
	 *				If the col does not exist, throw an ArrayIndexOutOfBoundsException
	 * @throws ArrayIndexOutOfBoundsException if the column is not in this matrix
	 */
	public static double getColumnTotal (double [][] matrix, int col)
	{
		double total = 0;
		
		if(isCol(matrix, col))
		{
			for (int row = 0; row < matrix.length; row++)
			{
				if (isRow(matrix, row) && matrix[row].length > col)
					total += matrix[row][col];
			}
		}
		else
		{
			throw new ArrayIndexOutOfBoundsException("COL: " + col);
		}			
		return total;
	}

	/** getHighestInRow finds the largest value one row of the array.
	 *
	 * @param matrix The two dimensional array
	 * @param row The number (0 based) of the row to find the largest
	 *
	 * @return The highest of the row array elements.  If the row does not exist
	 *         in matrix....YOU FILL IN THE REST.
	 */
	public static double getHighestInRow(double [][] matrix, int row)
	{
		double high = 0;
		if (matrix == null)
			throw new NullPointerException(); 
		if (isRow(matrix, row))
		{
			if (matrix[row].length > 0)
				high = matrix[row][0]; // starter
			for (int col = 1; col < matrix[row].length; col++)
			{
					if( matrix[row][col] > high)
						high = matrix[row][col];
			}
		}
		else 
			throw new ArrayIndexOutOfBoundsException("ROW: " + row);
		return high;
	}
	
	/** getLowestInRow finds the lowest value one row of the array.
	 *
	 * @param matrix The two dimensional array
	 * @param row The number (0 based) of the row to find the lowest
	 *
	 * @return The lowest of the row array elements.  If the row does not exist
	 *         in matrix....YOU FILL IN THE REST.
	 */
	public static double getLowestInRow(double [][] matrix, int row)
	{
		double low = 0;
		
		if (isRow(matrix, row))
		{
			if (matrix[row].length > 0)
				low = matrix[row][0]; // starter
			for (int col = 1; col < matrix[row].length; col++)
			{
					if( matrix[row][col] < low)
						low = matrix[row][col];
			}
		}
		else 
			throw new ArrayIndexOutOfBoundsException("ROW: " + row);
		return low;

	}
	
	/** isRow determines if the given row is in the matrix 
	 *
	 * @param matrix The two dimensional array
	 * @param row The number (0 based) of the row to check
	 *
	 * @return true if the row exists in the matrix and is not 
	 *         null, false otherwise
	 */
	 private static boolean isRow(double [][] matrix, int row)
	 {
	    boolean result = false;
		 
		 if (matrix != null && row >= 0 && row < matrix.length && 
		 	matrix[row] != null)
				result = true;
		
		 return result;
	 }
	 
	 /** isCol determines if the given col is in 
	  *  any row of the matrix 
	 *
	 * @param matrix The two dimensional array
	 * @param col The number (0 based) of the col to check
	 *
	 * @return true if the col exists in the matrix and is not 
	 *         null, false otherwise
	 */
	 private static boolean isCol(double [][] matrix, int col)
	 {
	    boolean result = false;
		 
		 if (matrix != null)
		 	for (int row = 0; row < matrix.length && !result; row++)
				if (matrix[row] != null)
					if (col < matrix[row].length)
						result = true;
		
		 return result;
	 }
		/** getCount counts the cells in a matrix 
	 *
	 * @param matrix The two dimensional array
	 *
	 * @return the number of cells in the matrix
	 */
	 private static int getCount(double [][] matrix)
	 {
	 	 int count = 0;
		 
	    if (matrix == null)
		 	throw new NullPointerException();
		 else
		 {
		 	for (int row = 0; row < matrix.length; row++)
			{
		 		if (isRow(matrix, row))
					count += matrix[row].length;
			}
		}
		return count;
	}
		
}