import java.util.Vector;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

public class GenericMethodsExercises{

    /* Generic Methods
       Convert the following method to be a generic method:
    */

    /**
     * Swap the elements at two indices
     * <p>Note: Does not check if the indices are valid</p>
     * @param array The array
     * @param index1 The index of one of the elements to swap
     * @param index2 The index of other element to swap
     */
    public static void swap2Original( Integer[] array, Integer index1, Integer index2 ){
        Integer temp = array[index1];
        array[ index1 ] = array[ index2 ];
        array[ index2 ] = temp;
    }
    /**
     * Swap the elements at two indices
     * <p>Note: Does not check if the indices are valid</p>
     * @param array The array
     * @param index1 The index of one of the elements to swap
     * @param index2 The index of other element to swap
     */
    public static <T> void swap2( T[] array, Integer index1, Integer index2 ){
        T temp = array[index1];
        array[ index1 ] = array[ index2 ];
        array[ index2 ] = temp;
    }


    /* Generic Methods
       Does the following method compile? If not, why?
    */

    /**	    
     * Sum all the numbers (whole or real) in a list
     * @param lst A list of Numbers
     * @return The sum of all of the numbers in lst
     */

    public static <T extends Number> double sumList( List<T> lst ){
        double total = 0.0;
        for( Number n : lst )
            total += n.doubleValue();
        return total;
    }

    /* Generic Methods
       4. Write a generic method to match the following Javadoc. Additionally,
       add code to main() to call the method twice (each with a different type).
    */

    /**
     * Finds the minimum value in a list between two indices
     * <p>Note: Does not check if the indices are valid</p>
     * @param lst The list object
     * @param startIndex The index to start looking at
     * @param endIndex The last index to consider
     * @return The smallest value in lst between startIndex and endIndex (inclusive) 
     */
    public static <T extends Comparable<T> > T smallest( List<T> lst, int startIndex, int endIndex ){
        T min = lst.get(startIndex);
        boolean found = false; // found at least 1 value smaller than the first one
        for( int i = startIndex + 1; i <= endIndex; ++i){
            T temp = lst.get(i);
            if( temp.compareTo( min ) < 0 ){
              //temp < min 
                min = temp;
                found = true;
            }
        }
        if( found == false ){
            System.out.println( "no value is smallest than the value at startIndex");
        }
        return min;
    }


    public static void main( String[] args ){

        /* Vector
           Declare a Vector object that stores the vowels in the English
           alphabet ('a', 'e', 'i', 'o', 'u' and 'y'). Display each of it's
           elements on a separate line.
        */




        /* Generic Methods
           Convert the following method to be a generic method:
        */
        Integer[] nums = {1, 2, 3};
        Character[] hello = {'h', 'e', 'l', 'l', 'o'};

        for( int i : nums ){
            System.out.print( i );
        }
        System.out.println("\n");

        swap2( nums, 1, 2 );
        for( int i : nums ){
            System.out.print( i );
        }
        System.out.println("\n");

        for( Character c : hello ){
            System.out.print( c );
        }
        System.out.println("\n");

        swap2( hello, 4, 3 );
        for( Character c : hello ){
            System.out.print( c );
        }
        System.out.println("\n");


        ArrayList<Number> numsAL = new ArrayList<Number>();
        for( int i : nums ){
            numsAL.add( i );
        }

        double tot = sumList( numsAL );
        System.out.println( "Total of ("+ numsAL + "): " + tot );


        /* Generic Methods
           Additionally, add code to main() to call the method twice (each with a different type).
         */

        Vector< Character > vowels = new Vector< Character >();
        vowels.add( 'a' );
        vowels.add( 'e' );
        vowels.add( 'i' );
        vowels.add( 'o' );
        vowels.add( 'u' );
        vowels.add( 'y' );

        for( char c : vowels ){
            System.out.println( c );
        }
        System.out.println();


        System.out.println("smallest( vowels, 1, 5)" );
        System.out.println( smallest( vowels, 1, 5) );

        ArrayList< Integer > primesList = new ArrayList< Integer >();
        primesList.add( 2 );
        primesList.add( 3 );
        primesList.add( 5 );
        primesList.add( 7 );
        primesList.add( 11 );
        primesList.add( 13 );
        primesList.add( 17 );

        Collections.shuffle(primesList);

        System.out.println("smallest( " + primesList + ", 0, primesList.size() - 1)" );
        System.out.println( smallest( primesList, 0, primesList.size() - 1) );

    }
}