public class ArrayListInt{
	private int[] arr;
	private int numElems;

	//creates an array with 1 slot, sets number of elements to 0
	public ArrayListInt(){
		arr = new int[1];
		numElems = 0;
	}


	//returns the number of elements currently stored in the list
	public int size() {
		return numElems;
	}

	//if index is in bounds: index >= 0 and index < numElems, does nothing
	//if index is out of bounds, displays an error and quits
	private void checkInBounds(int index) {
		if(index < 0 || index >= numElems) {
			System.out.println("Error: Array access out of bounds at index " +  index);
			System.exit(1);  //exit the program
		}
	}

	//returns the int stored in slot index
	public int get(int index) {
		checkInBounds(index);
		return arr[index];
	}

	//sets slot index to store newElement
	//returns the int previously stored at index
	public int set(int index, int newElement) {
		checkInBounds(index);
		int ret = arr[index];
		arr[index] = newElement;
		return ret;
	}


	//make sure that arr has at least minCapacity slots
	private void ensureCapacity(int minCapacity) {
		if(arr.length >= minCapacity) {
			return;
		}
		//find the new size
		int newSize = arr.length;
		while(newSize < minCapacity) {
			newSize *= 2;
		}
		//create the new array and copy elements over
		int[] newArr = new int[newSize];
		for(int index = 0; index < numElems; index++){
			newArr[index] = arr[index];
		}
		//now, we'll use this new array as our array
		arr = newArr;
	}

	//add newElement to the end of the list
	public void add(int newElement){
		ensureCapacity(numElems+1);
		arr[numElems] = newElement;
		numElems++;
	}


	//goal: arr[index] stores newElement
	//push remaining elements down
	public void add(int index, int newElement){
		//if adding to the last index, can use method we already wrote
		if(index == numElems) {
		   add(newElement);
		   return;
		}
		checkInBounds(index);
		ensureCapacity(numElems + 1 );
		//push elements down
		//pushing back-to-front makes copying (arguably) easier
		for(int pushing = numElems; pushing >= index + 1; pushing--) {
			arr[pushing] = arr[pushing - 1];
		}
		//arr[index] is "empty"; can now store newElement
		arr[index] = newElement;
		numElems++;
	}


	//removes the element at index; moving all later elements
	//up one slot.
	//Returns the removed element
	public int remove(int index){
		checkInBounds(index);
		int ret = arr[index];
		for(int pushIndex = index; pushIndex < numElems; pushIndex++) {
			arr[pushIndex] = arr[pushIndex + 1];
		}
		numElems--;
		return ret;
	}


	//find the first occurrence of element and return its index
	//if there is no occurrenct, return -1
	public int indexOf(int element) {
		for(int index = 0; index < numElems; index++) {
			if(arr[index] == element) {
				return index;
			}
		}
		return -1;
	}


	//returns true if element is in the list; false otherwise
	public boolean contains(int element) {
		return indexOf(element) != -1;
	}

	public String toString() {
		if(numElems == 0) {
			return "[ ]";
		}
		String ret = "[";
		for(int index = 0; index < numElems -1; index++) {
			ret += arr[index] + ", ";
		}
		ret += arr[numElems - 1] + "]";
		return ret;
	}

	public static void main(String[] args) {
		ArrayListInt test = new ArrayListInt();

		test.add(10);
		test.add(20);
		test.add(30);
		test.add(40);
		System.out.println("Added elements 10, 20, 30, 40");
		System.out.println(test);			  
		System.out.println("New element 100 at slot 1; push remainder down");
		test.add(1, 100);
		System.out.println(test);			  
		System.out.println("Testing indexOf: 30 is at slot " + test.indexOf(30));
		System.out.println("Testing indexOf: 7 is at slot " + test.indexOf(7));
		test.remove(2); 
		System.out.println("Remove the element at slot 2");
		System.out.println(test);			  
		System.out.println("Now, 30 is at slot " + test.indexOf(30));

	}
}

