import java.io.*;
import java.util.*;

/**
 * InteractiveDBTester takes a file as a command-line argument, parses into a CustomerDatabase, and 
 * allows you to run the following commands on the database:
 * 
 * d product 	- discontinues product from database
 * f customer 	- finds the wish list of the customer
 * h			- displays list of valid commands
 * i 			- displays information about the database
 * s product 	- searches for the given product in the database
 * r customer 	- removes the customer from the database
 * q 			- quit the program
 * 
 * @author Lindsey Gregor, CS 367
 *
 */
public class InteractiveDBTester {
    public static void main(String[] args) {
    	// Verify only one command-line argument given
		if (args.length != 1) {
			System.out.println("Please provide input file as command-line argument");
			System.exit(1); //quit
		}
		
		CustomerDatabase customerDB = new CustomerDatabase();
		
    	try {
    		// Import database from file
    		BufferedReader br = new BufferedReader(new FileReader(args[0]));
    		String line = "";
    		String delimiter = ",";
    		while ((line = br.readLine()) != null) {
    			String[] customer = line.split(delimiter);
    			// Add to customer database (username index 0)
    			customerDB.addCustomer(customer[0]);
    			// Add to customer's wish list
    			for (int i = 1; i < customer.length; i++) {
    				customerDB.addProduct(customer[0], customer[i]);
    			}
    		}
    		br.close();
    	} catch (Exception ex) {
    		System.out.println("Error: Cannot access input file");
    		System.exit(1);
    	}
    	
        Scanner stdin = new Scanner(System.in);  // for reading console input
        printOptions();
        boolean done = false;
        while (!done) {
            System.out.print("Enter option ( dfhisqr ): ");
            String input = stdin.nextLine();
            input = input.toLowerCase();  // convert input to lower case

            // only do something if the user enters at least one character
            if (input.length() > 0) {
                char choice = input.charAt(0);  // strip off option character
                String remainder = "";  // used to hold the remainder of input
                if (input.length() > 1) {
                    // trim off any leading or trailing spaces
                    remainder = input.substring(1).trim(); 
                }

                switch (choice) {
                
                case 'd':
                    boolean discontinued = customerDB.removeProduct(remainder);
                    if (discontinued) {
                    	System.out.println("product discontinued");
                    } else {
                    	System.out.println("product not found");
                    }
                    break;


                case 'f':
                    if (customerDB.containsCustomer(remainder)) {
                    	Iterator<Customer> dbIter = customerDB.iterator();
                    	while (dbIter.hasNext()) {
                    		Customer cust = dbIter.next();
                    		if (cust.getUsername().equals(remainder)) {
                    			System.out.print(cust.getUsername() + ":");
                    			List<String> wishlist = cust.getWishlist();
                    			if (wishlist != null) {
                    				Iterator<String> wlIter = wishlist.iterator();
                    				while (wlIter.hasNext()) {
                    					System.out.print(wlIter.next());
                    					if (wlIter.hasNext()) {
                    						System.out.print(",");
                    					}
                    				}
                    				break; //only one customer with that username in db
                    			}
                    		}
                    	}
                    	System.out.println();
                    } else {
                    	System.out.println("customer not found");
                    }
                    break;

                case 'h': 
                    printOptions();
                    break;

                case 'i':
                	// Print "Customers: <num customers>, Products: "
                    System.out.print("Customers: " + customerDB.size() + ", Products: ");
                    
                    // Add unique products to new temporary list
                    Iterator<Customer> dbIter = customerDB.iterator();
                    List<String> uniqueProducts = new ArrayList<String>();
                    while (dbIter.hasNext()) {
                    	Customer cust = dbIter.next();
                    	List<String> wishlist = cust.getWishlist();
                    	Iterator<String> wlIter = wishlist.iterator();
                    	while (wlIter.hasNext()) {
                    		String product = wlIter.next();
                    		
                    		// Add if product not already in uniqueProducts list
                    		if (!uniqueProducts.contains(product)) {
                    			uniqueProducts.add(product);
                    		}
                    	}
                    }
                    
                    // Print "<num unique products>"
                    System.out.println(uniqueProducts.size());
                    
                    // Print "# of products/customer: most <int>, least <int>, average <int>"
                    System.out.print("# of products/customer: most ");
                    
                    // Find customer with most number of products
                    int most = Integer.MIN_VALUE;
                    dbIter = customerDB.iterator();
                    while (dbIter.hasNext()) {
                    	Customer cust = dbIter.next();
                    	if (most < cust.getWishlist().size()) {
                    		most = cust.getWishlist().size();
                    	}
                    }
                    
                    System.out.print(most + ", least ");
                    
                    //Find customer with least number of products
                    int least = Integer.MAX_VALUE;
                    dbIter = customerDB.iterator();
                    while (dbIter.hasNext()) {
                    	Customer cust = dbIter.next();
                    	if (least > cust.getWishlist().size()) {
                    		least = cust.getWishlist().size();
                    	}
                    }
                    
                    System.out.print(least + ", average ");
                    
                    // Find average number of products per customer
                    int avg = 0;
                    dbIter = customerDB.iterator();
                    // Find total number of products for all customers
                    while (dbIter.hasNext()) {
                    	Customer cust = dbIter.next();
                    	avg += cust.getWishlist().size();
                    }
                    
                    // Divide avg by num customers
                    avg = avg / customerDB.size();
                    System.out.println(avg);
                                        
                    // Print "# of customers/product: most <int>, least <int>, average <int>"
                    System.out.print("# of customers/product: most ");
                    
                    // Find product in the most number of customer's wish lists using uniProducts list
                    most = Integer.MIN_VALUE;
                    List<String> mostPopProd = new ArrayList<String>(); //save most popular product(s) for later
                    Iterator<String> uniProdIter = uniqueProducts.iterator();
                    while (uniProdIter.hasNext()) {
                    	// Count number of customers with current product in their wish list
                    	int count = 0;
                    	String currProd = uniProdIter.next();
                    	dbIter = customerDB.iterator();
                    	while (dbIter.hasNext()) {
                    		Customer cust = dbIter.next();
                    		if (customerDB.hasProduct(cust.getUsername(), currProd)) {
                    			count ++;
                    		}
                    	}
                    	if (most == count) {
                    		// Add product to mostPopProd if count is same as most
                    		mostPopProd.add(currProd);
                    		most = count;
                      	} else if (most < count) {
                      		// Clear old mostPopProd and start a new one
                    		mostPopProd = new ArrayList<String>();
                    		mostPopProd.add(currProd);
                    		most = count;
                    	}
                    }
                    
                    System.out.print(most + ", least ");
                    
                    // Find product in the least number of customer's wish lists
                    least = Integer.MAX_VALUE;
                    uniProdIter = uniqueProducts.iterator();
                    while (uniProdIter.hasNext()) {
                    	//Count number of customers with current product in their wish list
                    	int count = 0;
                    	String currProd = uniProdIter.next();
                    	dbIter = customerDB.iterator();
                    	while (dbIter.hasNext()) {
                    		Customer cust = dbIter.next();                    		
                    		if (customerDB.hasProduct(cust.getUsername(), currProd)) {
                    			count ++;
                    		}
                    	}
                    	if (least > count) {
                    		least = count;
                    	}
                    }
                    
                    System.out.print(least + ", average ");
                    
                    // Find average number of customers per product
                    avg = 0;
                    uniProdIter = uniqueProducts.iterator();
                    while (uniProdIter.hasNext()) {
                    	// Count number of customers with current product in their wish list
                    	int count = 0;
                    	String currProd = uniProdIter.next();
                    	dbIter = customerDB.iterator();
                    	while (dbIter.hasNext()) {
                    		Customer cust = dbIter.next();
                    		if (customerDB.hasProduct(cust.getUsername(), currProd)) {
                    			count++;
                    		}
                      	}
                    	avg += count;
                    }
                                        
                    // Divide avg by num customers
                    if (uniqueProducts.size() > 0) {
                    	avg = avg / uniqueProducts.size();
                    } else {
                    	avg = 0; //handle no products in 
                    }
                    System.out.println(avg);
                    
                    // Print most popular product(s)
                    System.out.print("Most popular product: ");
                    Iterator<String> popProdIter = mostPopProd.iterator();
                    while (popProdIter.hasNext()) {
                    	System.out.print(popProdIter.next());
                    	if (popProdIter.hasNext()) {
                    		System.out.print(",");
                    	}
                    }
                    System.out.println(" [" + most + "]");
                    
                    break;
                    
                case 's':
                    if (!customerDB.containsProduct(remainder)) {
                    	System.out.println("product not found");
                    } else {
                    	// Print out product and customers with it in their wish list
                    	List<String> customers = customerDB.getCustomers(remainder);
                    	Iterator<String> custIter = customers.iterator();
                    	System.out.print(remainder + ":");
                    	while (custIter.hasNext()) {
                    		System.out.print(custIter.next());
                    		if (custIter.hasNext()) {
                    			System.out.print(",");
                    		}
                    	}
                    	System.out.println();
                    }
                    
                    break;

                case 'q':
                    done = true;
                    System.out.println("quit");
                    break;

                case 'r':
                    if (!customerDB.containsCustomer(remainder)) {
                    	System.out.println("customer not found");
                    } else {
                    	customerDB.removeCustomer(remainder);
                    	System.out.println("customer removed");
                    }
                	
                    break;

                default:  // ignore any unknown commands
                    break;
                }
            }
        }
        
        stdin.close();
    }

    /**
     * Prints the list of command options along with a short description of
     * one.  This method should not be modified.
     */
    private static void printOptions() {
        System.out.println("d <product> - discontinue the given <product>");
        System.out.println("f <customer> - find the given <customer>");
        System.out.println("h - display this help menu");
        System.out.println("i - display information about this customer database");
        System.out.println("s <product> - search for the given <product>");
        System.out.println("q - quit");
        System.out.println("r <customer> - remove the given <customer>");
    }
}