package program1;

import java.util.*;
/**
 * The CustomerDatabase class is used to represent a collection of Customer 
 * objects, each of which are made up of a username and wish list.
 * 
 * @author Stefen Showers
 */
public class CustomerDatabase {
	private List<Customer> cdb;         // the customer database   
	private List<String> templist; 		// local variable for getCustuomers and get Products
	private List<String> clist;
	private List<String> plist;			//list of unique products in database
	private List<String> fullplist;     //list of all products (includes duplicates)
	private int pcmost;
	private int pcleast;
	private int cpmost;
	private int cpleast;
	/**
     * Constructs an empty customer database.
     */
    public CustomerDatabase()     {
        cdb = new ArrayList<Customer>();
        clist = new ArrayList<String>();
        plist = new ArrayList<String>();
        fullplist = new ArrayList<String>();
        pcmost = 0;
    	pcleast = 0;
    	cpmost = 0;
    	cpleast = 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.
     * 
     * @param (c) this is the customer's username
     * @return void
     */
    void addCustomer(String c){
    	//use containsCustomer method to check for matches, else add Customer
    	if (cdb.size() > 0){
    		if (this.containsCustomer(c) != true){
        		cdb.add(new Customer(c));
        		clist.add(c);
        	}
        	else {
        		return;
        	}
    	}
    	else{
    		cdb.add(new Customer(c));
    		clist.add(c);
    	}
    }
    
    /**  NEED TO ADD: throw exception if customer doesn't exist
     * 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.
     * 
     * @param (c) this is the customer's name
     * @param (p) this is the product's name
     * @return void
     */
    void addProduct(String c, String p){
    	//iterate through cdb until we find where c == cust.getUsername()
    	Iterator<Customer> iter = iterator();
		while (iter.hasNext()){
			Customer cust = iter.next();
			//looking for the customer..
			if (c.equals(cust.getUsername())){
				Iterator<String> iter2 = cust.getWishlist().iterator();
    			while (iter2.hasNext()){
    				if (p.equals(iter2.next())) {
    					return;		//returns if product is found
    				}
    			}
    			cust.getWishlist().add(p);
    			if (plist.contains(p) == false){
    				plist.add(p);
    			}
    			fullplist.add(p);
				//"returns" whether the product was added or not
				return;
			}
		}
		//throw exception if customer doesn't exist
		//throw new java.lang.IllegalArgumentException();
    }
    
    /**
     * Return true iff customer c is in the database.
     * 
     * @param (c) this is the customer's name
     * @return boolean
     */
    boolean containsCustomer(String c){
    	//iterate through cdb until we find where c == cust.getUsername()
    	
    	if (cdb.size() > 0){
    		Iterator<Customer> iter = iterator();
    		while (iter.hasNext()){
        		//if match, return true
    			if (c.equals(iter.next().getUsername())){
        			return true;
        		}
    		}
    	}
    	//if no matches, return false
    	return false;
    }
    
    /**
     * Return true iff product p appears in at least one customer's wish list 
     * in the database.
     * 
     * @param (p) this is the product's name
     * @return boolean
     */
    boolean containsProduct(String p){
    	//iterate through cdb for all customers
    	Iterator<Customer> iter = iterator();
		while (iter.hasNext()){
			//at the first match, return true
			Iterator<String> iter2 = iter.next().getWishlist().iterator();
			while (iter2.hasNext()){
				if (p.equals(iter2.next())){
					return true;
				}
			}
		}

    	//if nothing found...
    	return false;
    }
    
    /**
     * Returns true iff product p is in the wish list for customer c. 
     * If customer c is not in the database, return false.
     * 
     * @param (c) this is the customer's name
     * @param (p) this is the product's name
     * @return boolean
     */
    boolean hasProduct(String c, String p){
    	//iterate through cdb until we find where c == cust.getUsername()
    	Iterator<Customer> iter = iterator();
		while (iter.hasNext()){
			Customer cust = iter.next();
    		//if match...
    		if (c.equals(cust.getUsername())){
    			//...check the wishlist contents
    			Iterator<String> iter2 = cust.getWishlist().iterator();
    			while (iter2.hasNext()){
    				if (p.equals(iter2.next())){
    					return true;
    				}
    			}
    		}
		}
    	//if not...
    	return false;
    }
    
    /**
     * Return the list of customers who have product p in their wish list. 
     * If product p is not in the database, return null.
     * 
     * @param (p) this is the product's name
     * @return List<String> of customer usernames
     */
    List<String> getCustomers(String p){
    	templist = new ArrayList<String>();
    	if (this.containsProduct(p)){
    		//iterate through all customers in cdb
        	Iterator<Customer> iter = iterator();
    		while (iter.hasNext()){
    			Customer cust = iter.next();
    			Iterator<String> iter2 = cust.getWishlist().iterator();
    			while (iter2.hasNext()){
    				if (p.equals(iter2.next())){
    					templist.add(cust.getUsername());
    				}
    			}
    		}
    		return templist;
    	}
    	return null;
    }
    
    /**
     * Return the wish list for the customer c. 
     * If a customer c is not in the database, return null.
     * 
     * @param (c) this is the customer's name
     * @return List<String> of product names in customer's wish list
     */
    List<String> getProducts(String c){
    	//iterate through cdb until we find where c == cust.getUsername()
    	if (this.containsCustomer(c)){
    		Iterator<Customer> iter = iterator();
    		while (iter.hasNext()){
    			Customer cust = iter.next();
        		//if match...
        		if (c.equals(cust.getUsername())){
        			return cust.getWishlist();
        		}
    		}
    	}
    	return null;
		//if customer not found, return null
    }
    
    /**
     * Return an Iterator over the Customer objects in the database. 
     * The customers should be returned in the order they were added to the 
     * database (resulting from the order in which they are in the text file).
     * 
     * @return new iterator
     */
    public Iterator<Customer> iterator(){
    	return cdb.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.
     * 
     * @param (c) this is the customer's name
     * @return boolean
     */
    boolean removeCustomer(String c){
    	if (this.containsCustomer(c)){   //not sure if this IF is necessary
    		//iterate through cdb until we find where c == cust.getUsername()
    		Iterator<Customer> iter = iterator();
    		while (iter.hasNext()){
    			Customer cust = iter.next();
        		//if match...
        		if (c.equals(cust.getUsername())){
        			cdb.remove(cust);
            		clist.remove(c);
                	return true;
        		}
    		}
    	}
    	return false;
    }
    
    /**
     * 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.
     * 
     * @param (p) this is the product's name
     * @return boolean
     */
    boolean removeProduct(String p){
    	if (this.containsProduct(p)){
    		//iterate through all of cdb
    		Iterator<Customer> iter = iterator();
    		while (iter.hasNext()){
    			Customer cust = iter.next();
        		//check each wishlist for the product
    			Iterator<String> iter2 = cust.getWishlist().iterator();
    			while (iter2.hasNext()){
    				if (p.equals(iter2.next())) {
        				cust.getWishlist().remove(p);
        				plist.remove(p);
        			}
    			}
        	}
    		return true;
    	}
    	return false;
    }
    
    /**
     * Return the number of customers in this database.
     * 
     * @return int
     */
    int size(){
    	//utilizes the existing size method
    	return cdb.size();
    }
    
    /**
     * Returns an integer array with most of the necessary metrics for the 'i' 
     * option from the InteractiveDBTester. Specifically:
     * position 0 is the unique products count
     * position 1 is the products/customer maximum - number of products on largest wish list
     * position 2 is the products/customer minimum - number of products on smallest wish list
     * position 3 is the customer/products maximum - number of customers on with most popular product
     * position 4 is the customer/products minimum - number of customers with least popular product
     * 
     * @return int[5]
     */
    int[] allMetrics(){
    	int[] metrics = new int[5];
    	
    	//values in the following are associated by position
    	String[] productnames = new String[plist.size()];
    	int[] customercount = new int[plist.size()];
    	
    	//loop through fullplist and add unique items to productname[i]
    	//add 1 for every product counted to customercount[i];
    	int i=0; 
    	Iterator<String> iter = plist.iterator();
    	while (iter.hasNext()){
    		productnames[i] = iter.next();
    		Iterator<String> iter2 = fullplist.iterator();
    		while (iter2.hasNext()){
    			if (iter2.next().equals(productnames[i])){
    				customercount[i]++;
    			}
    		}
    		i++;
    	}
    	
    	//give cpmost an initial value, then skip position 0 check in loop
    	cpmost = customercount[0];
    	//loop through plist to find largest number
    	//set this equal to cpmost
    	for (int j=1; j < plist.size(); j++){
    		if (customercount[j] > cpmost){
    			cpmost = customercount[j];
    		}
    	}
    	
    	//give cpleast an initial value, then skip position 0 check in loop
    	cpleast = customercount[0];
    	//loop through customercount to find smallest number
    	//set this equal to cpleast
    	for (int k=1; k < plist.size(); k++){
    		if (customercount[k] < cpleast){
    			cpleast = customercount[k];
    		}
    	}
    	
    	//give pcmost an initial value
    	pcmost = 0;
    	//iterate through cdb and find the max cust.getWishlist().size()
    	Iterator<Customer> iter3 = iterator();
    	while(iter3.hasNext()){
    		int wlistlen = iter3.next().getWishlist().size();
    		if (wlistlen > pcmost){
    			pcmost = wlistlen;
    		}
    	}
    	
    	//give pcleast an initial value
    	pcleast = pcmost;
    	//iterate through cdb and find the max cust.getWishlist().size()
    	Iterator<Customer> iter4 = iterator();
    	while(iter4.hasNext()){
    		int wlistlen = iter4.next().getWishlist().size();
    		if (wlistlen < pcleast){
    			pcleast = wlistlen;
    		}
    	}
    	
    	metrics[0] = plist.size();
    	metrics[1] = pcmost;
    	metrics[2] = pcleast;
    	metrics[3] = cpmost;
    	metrics[4] = cpleast;
    	
    	return metrics;
    }
    
    /**
     * Returns a string Array with the most popular product(s)
     * Used by InteractiveDBTester
     * 
     * @return List<String>
     */
    List<String> popProducts(int count){
    	List<String> lst = new ArrayList<String>();
    	Iterator<String> iter = plist.iterator();
    	while(iter.hasNext()){
    		String prd = iter.next();
    		if(this.getCustomers(prd).size()==count){
    			lst.add(prd);
    		}
    	}
    	return lst;
    }
    
    
}
