/**
 * @author CodyScott
 * @organization phcorner.net
 * This simple app uses the power of LinkList, List, Iterator and HashMap classes
 * from the Java Core library.
 */

import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class MainApp {
	static String[] defaultNames = {"Pedro","Jose","William","Mark","Totoy","Raul","Nelson","Pepe","Jawo","Tintoy"};
	static Scanner in = new Scanner(System.in);
	static List<String> nameList = new LinkedList<String>();
	

	/**
	 * This is the entry point of the app
	 * @param args
	 */
	public static void main(String[] args) {
		populateDefaultNames();
		while(true){
			try{
				displayMenu();
				int choice = getMenuChoice();
				performChoice(choice);
			} catch(InputMismatchException i){
				in.next();
				System.out.println("Not valid! Try again!");
			}
			
		}
	}
	
	/**
	 * This is a helper method.
	 * When the app runs, it populates the defaults names.
	 */
	static void populateDefaultNames(){
		for(String s: defaultNames){
			nameList.add(s);
		}
	}
	
	/**
	 * THis is a helper method. It just displays the menu options
	 */
	static void displayMenu(){
		System.out.println("\nMENU: Choose Operation");
		System.out.println("1-insert 2-delete 3-view 4-search");
	}

	/**
	 * This is a helper method. It just reads user menu choice input
	 * @return
	 */
	static int getMenuChoice(){
		int choice;
		choice = in.nextInt();
		return choice;
	}
	
	/**
	 * This function assigns which method to use based on the user input
	 * from the menu option
	 * @param choice
	 */
	static void performChoice(int choice){
		switch(choice){
			case 1: performInsert(); break;
			case 2: performDelete(); break;
			case 3: performView(); break;
			case 4: performSearch(); break;
			default: System.out.println("Not valid! Try again!");
		}
	}

	/**
	 * This method performs the search function.
	 * First, user enters the name to search. Then method
	 * will check if name is present. And also method will check
	 * if there are duplicates of this name. Then it prints the name and index number.
	 */
	private static void performSearch() {
		String nameToSearch = "";
		System.out.print("SEARCH: ");
		nameToSearch = in.next();
		if(nameList.contains(nameToSearch)){
			HashMap<Integer,String> duplicates = findDuplicates(nameToSearch);
			displayDuplicatesMap(duplicates);
		} else {
			System.out.println("No such name found.");
		}

	}

	/**
	 * This function performs the view.
	 * It loops inside the nameList and displays all the names
	 */
	private static void performView() {
		if(isEmpty()==false){
			displayList();
		} else {
			displayEmptyMessage();
		}
		
	}

	/**
	 * This method performs the delete function.
	 * First, user enters a name to delete, then method checks if
	 * name is in the list. If not on the list, method simply won't do
	 * anything. If name is in the list, method display if there are duplicate names
	 * and then delete one of the names. Or if there is only one name on the list, method
	 * deletes that name also.
	 */
	private static void performDelete() {
		String nameToDelete = "";
		System.out.print("DELETE: ");
		nameToDelete = in.next();
		if(nameList.contains(nameToDelete)){
			HashMap<Integer,String> duplicates = findDuplicates(nameToDelete);
			if(duplicates.size()>1){
				displayDuplicatesMap(duplicates);
				nameList.remove(nameToDelete);
				System.out.println("One " + nameToDelete + " has been deleted");
			} else {
				nameList.remove(nameToDelete);
				System.out.println(nameToDelete + " successfully deleted!");
			}
		} else {
			System.out.println("No such name found.");
		}
	}

	/**
	 * This method performs the name insertion on the list.
	 * Once it inserted the name, it just prints a message.
	 */
	private static void performInsert() {
		String nameToInsert="";
		System.out.print("INSERT: ");
		nameToInsert = in.next();
		nameList.add(nameToInsert);
		System.out.println(nameToInsert + " inserted successfully");
		
	}
	
	/**
	 * This is a helper method that checks
	 * if the nameList has at least 1 name on it or empty.
	 * @return false if empty or true otherwise
	 */
	private static boolean isEmpty(){
		if(nameList.size()<=0 || nameList==null){
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * This is a helper method.
	 * It just display message.
	 */
	private static void displayEmptyMessage() {
		System.out.println("No name on the list.");
		
	}
	
	/**
	 * This is a helper method, it loops inside the nameList
	 * and display all names
	 */
	private static void displayList(){
		for(Object s : nameList){
			System.out.println(s);
		}
		System.out.println("-- " + nameList.size() + " total names --" );
	}
	
	/**
	 * This is a helper method. It finds duplicate of the name entered by user
	 * from the nameLis
	 * @param name
	 * @return HashMap
	 */
	private static HashMap<Integer, String> findDuplicates(String name){
		HashMap<Integer,String> duplicatesMap = new HashMap<>();
		if(nameList.contains(name)){
			int counter=0;
			for(String n : nameList){
				if(n.equals(name)){
					duplicatesMap.put(counter, name);
				}
				counter++;
			}
		}
		return duplicatesMap;
	}
	
	/**
	 * This is a helper method. It loops inside the map list
	 * and displays the name and its index number on the list
	 * @param map
	 */
	private static void displayDuplicatesMap(HashMap<Integer,String> map){
		Iterator<Integer> it = map.keySet().iterator();
		while(it.hasNext()){
			Object o = it.next();
			System.out.println(map.get(o) + " on index " + o);
		}
	}
	
}
