package simulator;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Scanner;

/*
 * CustomerReader.java
 * Created on Feb 4, 2005
 *
 */

/**
 *  CustomerReader - This class is responsible for reading in all the
 *  customers from a particular file
 *  @author Ping
 *
 */
public class CustomerReader
{
    // This string is used to divide the customers in the input file.
    public static String CUSTOMER_DIVIDER = "----";
    
    public CustomerReader()
    {
        
    }
    
    
    public Collection<Customer> readCustomers(String fileName) throws FileNotFoundException, CustomerReadException
    {	
    	DataReader reader = new DataReader(fileName);
        ArrayList<Customer> customers = new ArrayList<Customer>();
        
        Scanner scanner;

        String dataLine = reader.readDataLine();
        // while there are more lines to read
        while(dataLine != null)
        {
        	String customerName = dataLine.trim();
        
            // read the time entered
            dataLine = reader.readDataLine();
            scanner = new Scanner(dataLine);
            int enteredHour = scanner.nextInt();
            int enteredMinutes = scanner.nextInt();
            
            // read in the customer type
            String customerType = reader.readDataLine().trim();
            
            // read in the exit strategy
            dataLine = reader.readDataLine().trim();
            Customer.ExitStrategy exitStrategy;
            // select the right exit strategy
            if(dataLine.equalsIgnoreCase(
                    Customer.ExitStrategy.EMPTY_WISH_LIST.type))
            {
                exitStrategy = Customer.ExitStrategy.EMPTY_WISH_LIST;
            }
            else if(dataLine.equalsIgnoreCase(
                    Customer.ExitStrategy.SET_TIME.type))
            {
                exitStrategy = Customer.ExitStrategy.SET_TIME;
            }
            else if(dataLine.equalsIgnoreCase(
                    Customer.ExitStrategy.PARK_CLOSING_TIME.type))
            {
                exitStrategy = Customer.ExitStrategy.PARK_CLOSING_TIME;
            }
            else
            {
                throw new CustomerReadException("Read in unknown exit strategy: " +
                        dataLine);
            }
            
            // now read in the time if the exit strategy is based on a set time
            // if not, then this line contains the first item on the wish list
            dataLine = reader.readDataLine();
            int exitHour = 0;
            int exitMinutes = 0;
            if(exitStrategy == Customer.ExitStrategy.SET_TIME)
            {
                scanner = new Scanner(dataLine);
                exitHour = scanner.nextInt();
                exitMinutes = scanner.nextInt();
                
                // since we read in a line that only exists if the exit
                // strategy is to go home at a set time, we must
                // read in the next line such that we are in the same
                // position as we would be if the exit strategy is different
                dataLine = reader.readDataLine();
            }
            
            ArrayList<PrioritizedElement<String, Integer>> wishList =
                new ArrayList<PrioritizedElement<String, Integer>>();                
            
            // keep going until we have read in a divider
            while(dataLine != null && !dataLine.equals(CUSTOMER_DIVIDER))
            {
            	scanner = new Scanner(dataLine);
                // read in the priority and the ride name
                int priority = scanner.nextInt();
                String rideName = scanner.nextLine().trim();
                // add the wish list item to the list
                wishList.add(new PrioritizedElement<String, Integer>(
                        rideName, priority));
                
                // read in the next item
                dataLine = reader.readDataLine();
            }
            
            customers.add(customerFactory(customerName, 
                    enteredHour, enteredMinutes, customerType, 
                    exitStrategy, exitHour, exitMinutes, wishList));
            
            // we now skip past the separater if there was one.  
            // if it was null, we'll still be at null so its ok.
            dataLine = reader.readDataLine();
        }
        
        return customers;
    }


    /**
     * 
     * @param customerName
     * @param enteredHour
     * @param enteredMinutes
     * @param customerType
     * @param exitStrategy
     * @param exitHour
     * @param exitMinutes
     * @param wishList
     * @return
     * @throws CustomerReadException
     */
    protected Customer customerFactory(String customerName, 
            int enteredHour, int enteredMinutes, 
            String customerType, Customer.ExitStrategy exitStrategy, 
            int exitHour, int exitMinutes, 
            ArrayList<PrioritizedElement<String, Integer>> wishList) 
        throws CustomerReadException
    {
        Customer customer;
        // create the appropriate customer type
        if(customerType.equalsIgnoreCase(
                PriorityBasedCustomer.CUSTOMER_TYPE))
        {
        	customer = new PriorityBasedCustomer(customerName, 
                    wishList, exitStrategy, 
                    new Time(enteredHour, enteredMinutes),
                    new Time(exitHour, exitMinutes));
        }
        else if(customerType.equalsIgnoreCase(
                ClosestRideFirst.CUSTOMER_TYPE))
        {	
        	customer = new ClosestRideFirst(customerName, 
                    wishList, exitStrategy, 
                    new Time(enteredHour, enteredMinutes),
                    new Time(exitHour, exitMinutes));
        }
        else if(customerType.equalsIgnoreCase(
                ShortestTimeFirst.CUSTOMER_TYPE))
        {
            customer = new ShortestTimeFirst(customerName, 
                    wishList, exitStrategy, 
                    new Time(enteredHour, enteredMinutes),
                    new Time(exitHour, exitMinutes));
        }
        else
        {
            throw new CustomerReadException("Read in unknown customer type: " +
                    customerType);
        }
    	
        return customer;
    }
}

