///////////////////////////////////////////////////////////////////////////////
// Title:            Programming Assignment 1 - CustomerDatabase
// Files:            CustomerDatabase.java, InteractiveDBTester.java
// Semester:         Summer 2014
//
// Author:           Jonathan Block (jblock@epic.com - jonoblock@yahoo.com)
// CS Login:         N/A at this point; General UW login is block3
// Lecturer's Name:  Beck Hasti
// Lab Section:      2
//////////////////////////// 80 columns wide //////////////////////////////////

import java.util.*;
/**
 * The CustomerDatabase class is used to represent a collection of Customer objects.
 * A list of Customers is the primary database concept.
 *
 * <p>Bugs: Likely will be issues if methods are used before constructor is called.
 * 			No known bugs.
 *
 * @author Jonathan Block
 */
public class CustomerDatabase {
	private List<Customer> customers;   //List of customer names - primary database concept
	private Customer cust;              //Customer variable used in various methods
	private Iterator<Customer> iter;    //Iterator variable used in various methods
	private List<String> list;          //List variable used in various methods
	/**
	 * Constructs an empty customers ArrayList
	 *
	 */
	public CustomerDatabase() {
		customers = new ArrayList<Customer>();
	}
	/**
	 * Adds a Customer to the end of the customers list
	 *
	 * @param c the customer Username (assumed lower case) which will 
	 * create a new Customer object and add to customers list
	 */
	void addCustomer(String c) {        //Assumption is that c has already been converted to lower case
		if (c == null) {
			throw new IllegalArgumentException();	//Check that parameter entered is not null
		}
		if (containsCustomer(c)) {       //Check to see if the customer is already there
			return;
		}
		customers.add(new Customer (c));//Create new customer and add to end of list
	}
	/**
	 * Adds a product to a Customer's wish list
	 *
	 * @param c Customer's Username
	 * @param p product description
	 */
	void addProduct(String c, String p) {
		if (c == null || p == null) {
			throw new IllegalArgumentException();	//Check that parameters entered are not null
		}
		if (!containsCustomer(c)) {
			throw new IllegalArgumentException();
		}
		cust = findCustomer(c);
		List<String> custList;
		custList = cust.getWishlist();
		if (!hasProduct(c, p)) {			//Only add if customer does not already have it on the wish list
			custList.add(p);
		}
	}
	/**
	 * Checks to see if a specific Customer exists in customers list
	 *
	 * @param c Customer's Username
	 * @return true if found, otherwise false
	 */
	boolean containsCustomer(String c) {
		if (c == null) {
			throw new IllegalArgumentException();	//Check that parameter entered is not null
		}
		iter = iterator();
		while (iter.hasNext()) {		//Iterate over customers and check if Username matches c
			cust = iter.next();
			if (c.equals(cust.getUsername())) {
				return true;
			}
		}
		return false;
	}
	/**
	 * Checks to see if a product is in any Customer's Wishlist
	 *
	 * @param p product description
	 * @return true if found, otherwise false
	 */
	boolean containsProduct(String p) {
		if (p == null) {
			throw new IllegalArgumentException();	//Check that parameter entered is not null
		}
		iter = iterator();
		while (iter.hasNext()) {		//Iterate over customers and check hasProduct
			cust = iter.next();
			if (hasProduct(cust.getUsername(), p)) {
				return true;
			}
		}
		return false;
	}
	/**
	 * Checks to see if a product is in a specific Customer's Wishlist
	 *
	 * @param c Customer's Username
	 * @param p product description
	 * @return true if found, otherwise false
	 */
	boolean hasProduct(String c, String p) {
		if (c == null || p == null) {
			throw new IllegalArgumentException();	//Check that parameters entered are not null
		}
		if (!containsCustomer(c)) {
			return false;				//Return false if there is no Customer for c in the database
		}
		cust = findCustomer(c);
		list = cust.getWishlist();
		if (list.contains(p)) {
			return true;				//If Customer's Wishlist contains p return true
		}
		return false;                   //If never found return false
	}
	/**
	 * Gather a list of Customer objects that have a certain product on their Wishlist
	 *
	 * @param p product description
	 * @return list of customer objects with the product on their Wishlist
	 */
	List<String> getCustomers(String p) {
		if (p == null) {
			throw new IllegalArgumentException();	//Check that parameter entered is not null
		}
		if (!containsProduct(p)) {
			return null;				//Returns null if product not found
		}
		List<String> custList = new ArrayList<String>();	//Create list to return Customers' Usernames
		iter = iterator();
		while (iter.hasNext()) {		//Iterate over customers and check hasProduct
			cust = iter.next();
			if (hasProduct(cust.getUsername(), p)) {
				custList.add(cust.getUsername());
			}
		}
		return custList;
	}
	/**
	 * Gather a specific Customer's Wishlist
	 *
	 * @param c Customer's Username
	 * @return Customer's Wishlist
	 */
	List<String> getProducts(String c) {
		if (c == null) {
			throw new IllegalArgumentException();	//Check that parameter entered is not null
		}
		if (!containsCustomer(c)) {
			return null;				//Return null if customer is not found
		}
		cust = findCustomer(c);
		list = cust.getWishlist();
		return list;
	}
	/**
	 * Creates an iterator for the customers list
	 *
	 * @return iterator for the customers list
	 */
	Iterator<Customer> iterator() {
		return customers.iterator();
	}
	/**
	 * Remove a customer from the database
	 *
	 * @param c Customer's Username
	 * @return false if customer is not in database, otherwise true
	 */
	boolean removeCustomer(String c) {
		if (c == null) {
			throw new IllegalArgumentException();	//Check that parameter entered is not null
		}
		if (!containsCustomer(c)) {
			return false;				//Return false if customer is not in the database
		}
		cust = findCustomer(c);
		customers.remove(cust);			//Remove Customer from customers
		cust = null;					//Delete Customer entirely
		return true;
	}
	/**
	 * Remove a product from all Customer objects' Wishlists
	 *
	 * @param p product description
	 * @return false if product is not in the database, otherwise true
	 */
	boolean removeProduct(String p) {
		if (p == null) {
			throw new IllegalArgumentException();	//Check that parameter entered is not null
		}
		if (!containsProduct(p)) {
			return false;				//Return false if product is not in the database at all
		}
		iter = iterator();
		while (iter.hasNext()) {
			cust = iter.next();
			if (hasProduct(cust.getUsername(), p)) {
				list = cust.getWishlist();
				list.remove(p);
			}
		}
		return true;
	}
	/**
	 * Find the number of Customer objects in customers list
	 *
	 * @return number of Customer objects
	 */
	int size() {
		return customers.size();
	}
	/**
	 * Retrieve the actual customer object associated with a Username
	 * This is not a required method, but an easy way to modularize for my class
	 *
	 * @param c Customer's Username
	 * @return Customer object that corresponds to username c
	 */
	private Customer findCustomer(String c) {   //Return Customer with username c from customers
		iter = iterator();				//Assume we have already checked to see if Customer is in customers
		while (iter.hasNext()) {
			cust = iter.next();
			if (c.equals(cust.getUsername())) {
				return cust;
			}
		}
		return cust;                 //This was just to get rid of a eclipse red underline
	}
}
