
///////////////////////////////////////////////////////////////////////////////
//                   ALL STUDENTS COMPLETE THESE SECTIONS
// Main Class File:  InteractiveDBTester.java
// File:             CustomerDatabase
// Semester:         CS367 Summer 2014
//
// Author:           Dan Willmer - dan.willmer@gmail.com
import java.util.*;
/**
 * The Customer Database class is used to represent a group of customers and their wishlists. 
 * 
 * @author Dan Willmer, CD 367 student, copyright 2014
 */
public class CustomerDatabase{
	ArrayList<Customer> customers;
	List<String> products = new ArrayList<String>();
	int size;
	
	/*
	 * Constructs a customer database with a size of 0;
	 */
	public CustomerDatabase(){
		customers = new ArrayList<Customer>();
		size = 0;
	}
	/*
	 * Add a customer with the given username c to the end of the database. 
	 * If a customer with username c is already in the database, just return.
	 */
	public void addCustomer(String c) {
		if (containsCustomer(c)){
			return;
		}
		Customer newCustomer = new Customer(c);
		customers.add(newCustomer);
	}
	/*
	 * Add the given product p to the wish list for customer c in the database. 
	 * If customer c is not in the database throw a java.lang.IllegalArgumentException.
	 * If p is already in the wish list for customer c, just return.
	 */
	public void addProduct(String c, String p) {
		
		List<String> wishlist;
		try{
			if (containsCustomer(c)){
				if(hasProduct(c, p))
					return;
				else{
					wishlist = getProducts(c);
					wishlist.add(p);
					if(!(this.products.contains(p))){
						this.products.add(p);
					}
				}
			}
			else return;
		}catch (IllegalArgumentException exc1){
			System.out.println("Customer not found in database");
			}
	}
/*
 * Returns true if the customer is in the database
 */
	public boolean containsCustomer(String c) {
		Customer tempCustomer;
		boolean found = false;
		Iterator<Customer> itr = customers.iterator();
		while(itr.hasNext())
		{
			tempCustomer = itr.next();
			if (c.equals(tempCustomer.getUsername()))
			{
				found = true;
			}
		}
		return found;
	}

	 /*
	  * Returns true if product p appears in at least one customer's wish list in the database.
	  */
	public boolean containsProduct(String p) {
		Customer tempCustomer;
		List<String> tempWishlist;
		boolean found = false;
		Iterator<Customer> itr = customers.iterator();
		while(itr.hasNext() && !found)
		{
			tempCustomer = itr.next();
			tempWishlist = tempCustomer.getWishlist();
			Iterator<String> itr2 = tempWishlist.iterator();
			while(itr2.hasNext() && !found)
			{
				if (p.equals(itr2.next()))
				{
					found = true;
				}
			}
		}
		return found;
	}

	 /*
	  * Returns true if product p is in the wish list for customer c. 
	  * If customer c is not in the database, return false.
	  */
	public boolean hasProduct(String c, String p) {
		List<String> wishlist;
		boolean found = false;
		if (containsCustomer(c)){
			wishlist = getProducts(c);
			if (wishlist.contains(p))
				found = true;
		}
		return found;
	}

	 /*
	  * Return the list of customers who have product p in their wish list. 
	  *	If product p is not in the database, return null.
	  */
	public List<String> getCustomers(String p) {
		List<String> customerList = new ArrayList<String>();
		List<String> tempWishlist;
		Customer tempCustomer;
		Iterator<Customer> itr = customers.iterator();
		
		while(itr.hasNext())
		{
			tempCustomer = itr.next();
			tempWishlist = tempCustomer.getWishlist();
			if (tempWishlist.contains(p))
				customerList.add(tempCustomer.getUsername());
		}
		return customerList;
	}

	 /*
	  * Return the wish list for the customer c. 
	  * If a customer c is not in the database, return null.
	  */
	public List<String> getProducts(String c) {
		List<String> wishlist = null;
		Customer tempCustomer;
		Iterator<Customer> itr = customers.iterator();
		boolean found = false;
		
		while(itr.hasNext() && !found)
		{
			tempCustomer = itr.next();
			if (tempCustomer.getUsername().equals(c)){
				found = true;
				wishlist = tempCustomer.getWishlist();
			}
		}
		return wishlist;
	}

	 /*
	  * Returns an iterator from the customers list
	  */
	public Iterator<Customer> iterator() {
		return customers.iterator();
	}

	 /*
	  * Remove customer c from the database. 
	  * If customer c is not in the database, return false; otherwise (i.e., the removal is successful) return true.
	  */
	public boolean removeCustomer(String c) {
		boolean found = false;
		Customer tempCustomer;
		Iterator<Customer> itr = customers.iterator();
		while(itr.hasNext() && !found)
		{
			tempCustomer = itr.next();
			if (c.equals(tempCustomer.getUsername()))
			{
				found = true;
				customers.remove(tempCustomer);
			}
		}
		return found;
	}
/*
 * Remove product p from the database, i.e., remove product p from every wish list in which it appears. 
 * If product p is not in the database, return false; otherwise (i.e., the removal is successful) return true	
 */
	public boolean removeProduct(String p) {
		Customer tempCustomer;
		List<String> tempWishlist;
		boolean found = false;
		Iterator<Customer> itr = customers.iterator();
		while(itr.hasNext())
		{
			tempCustomer = itr.next();
			tempWishlist = tempCustomer.getWishlist();
			if (tempWishlist.remove(p))
				found = true;			//only set to true if p is removed so I avoid setting found back to false
		}
		products.remove(p);
		return found;
	}
	/*
	 * Return the number of customers in the database
	 */
	public int size() {
		return size;
	}
	/*
	 *  Evaluate the stats involving the number of customers per product.
	 *  Returns stats in the form of:  "# of customers/product: most integer, least integer, average integer"
	 */
	public String CustomersPerProductStats(){ 
		int count, average;
		int stats = 0;
		int totalCustomers = 0;
		int highCount = 0;
		int lowCount = 0;
		String result;
		Iterator<String> itr = products.iterator();
		while(itr.hasNext()){
			count = getCustomers((String) itr.next()).size();
			if (count > highCount)
				highCount = count;
			if (lowCount == 0)
				lowCount = count;
			if (count < lowCount)
				lowCount = count;
			totalCustomers += count;
		}
		average = totalCustomers / products.size(); 
		result = "# of customers/product: most "+highCount+", least "+lowCount+", average "+ average;
				
		return result;
	}
	/*
	 * Displays stats about the number of products per customer
	 * returns stats in the form of: "# of products/customer: most integer, least integer, average integer"
	 */
	public String ProductsPerCustomerStats(){
		int count;
		int totalProducts = 0;
		int highCount = 0;
		int lowCount = 0;
		int average;
		String result;
		Iterator<Customer> itr = customers.iterator();
		
		while(itr.hasNext()){
			count = getProducts(itr.next().getUsername()).size();
			if (count > highCount)
				highCount = count;
			if (lowCount == 0)
				lowCount = count;
			if (count < lowCount)
				lowCount = count;
			totalProducts += count;
		}
		average = totalProducts / customers.size();
		result = "# of products/customer: most "+highCount+", least "+lowCount+", average "+ average;
		return result;
	}
	/*
	 * Returns a basic count of the customer and product numbers
	 */
	public String BasicCount(){
		return "Customers: " + customers.size() + ", Products: " + products.size();	
	}
	/*
	 * Returns information about the popular product in the form of product [count]
	 */
	public String MostPopularProduct(){
		String result = null;
		String tempProduct;
		int count = 0;
		int highCount = 0;
		int lowCount = 0;
		Iterator<String> itr = products.iterator();
		while(itr.hasNext()){
			tempProduct = itr.next();
			count = getCustomers(tempProduct).size();
			if (count == highCount)
				result = result + ", " + tempProduct;
			if (count > highCount){
				highCount = count;
				result = tempProduct;
			}
		}
		result = "Most popular product: " + result + " [" + highCount + "]";
		return result;
	}
}
