// SortingDemo2.java
// Demonstrates selection sort using file of short integers.
// 
// Replaces the array with a bigger array when necessary.
//
// Uses, in this directory:
//    SortingDemoExceptions.java
//    TextFileInput.java
//    TextFileOutput.java
//
// To compile this program in Java 1.4, type:
//    javac -source 1.4 SortingDemo2.java
// (Compile it normally in Java 1.5 or later.)
//
// To run this program with assertions enabled, type:
//    java -ea SortingDemo2
// (Otherwise, assertions are disabled.)


/**
 * Program which sorts the numbers in a text file
 * containing short integers, one number per line,
 * and then prints them to another text file whose
 * filename is the input file's name prefixed
 * by "sorted-".
 *
 * @author Dorothy L. Nixon
 */
public class SortingDemo2
{
   /**
    * Main method.
    *
    * @param args command-line arguments.
    *             Just one command-line argument
    *             is needed for the input file.
    */
   public static void main(String[] args)
   {
      final int MAX_NUMBER_OF_NUMBERS = 40;

      if ( args.length == 0 )
      {
         System.out.println("This program sorts short integers");
         System.out.println("from the file specified by a");
         System.out.println("command-line argument.");
         System.exit(0);
      } // if

      final String inputFileName = args[0];
      final String outputFileName = "sorted-" + inputFileName;

      short[] numbersArray = new short[MAX_NUMBER_OF_NUMBERS];

      // Read numbers into numbersArray from input file:
      int subArrayLength = inputFromFile(inputFileName,
                                         numbersArray);

      // Sort numbers in ascending order if possible.
      // Otherwise, print an error message and quit.
      SortingDemoExceptions.selectionSort(numbersArray,
                                          subArrayLength);

      // Write numbers in numbersArray to output file:
      outputToFile(outputFileName, numbersArray, subArrayLength);

      // Print message indicating successful completion:
      System.out.println("File " + outputFileName
                                 + " has been created.");
   }  // method main

   /**
    * Reads short integers from the specified
    * file to the specified array.  Returns the
    * number of numbers that have been read,
    * if successful.
    *
    * If the number of numbers in the file
    * exceeds the length of the array, then a 
    * user-friendly error message is printed
    * to the console, and the program is
    * terminated with error code 1.
    *
    * @param filename name of file containing
    *                 short integers, one per line.
    *                 The number of numbers in the
    *                 file is not known in advance.
    * @param numbers array into which numbers in 
    *                 the file are read.
    *
    * @return length of subarray of <code>numbers</code>
    *         containing actual numbers read from the file.
    */
   private static int inputFromFile(String filename,
                                    short[] numbers)
   {
      TextFileInput in = new TextFileInput(filename);

      // Read numbers into array:
      int lengthFilled = 0;
      String line = in.readLine();   // read first line in file
      while ( lengthFilled < numbers.length && line != null )
      {
         // If the array is already filled,
         // replace it with a bigger array:
         if ( lengthFilled >= numbers.length )
         {
            short[] temp = new short[numbers.length
                                     + lengthFilled + 2];
            for (int i = 0; i < numbers.length; i++)
               temp[i] = numbers[i];
            numbers = temp;
         }  // if

         // Put the most recently read number in the
         // array and continue reading from the file:
         numbers[lengthFilled] = Short.parseShort(line);
         line = in.readLine();       // read next line in file
         lengthFilled++;
      } // while

      // Check to see if all the numbers in the file were read.
      // If not, then the array wasn't big enough to hold them all.
      // In that case, print an error message and quit.
      if ( line != null )            // i.e. if end-of-file not reached
      {
         System.out.println("File contains too many numbers.");
         System.out.println("This program can process only "
                             + numbers.length + " numbers.");
         System.exit(1);
      }  // if

      // Release file for re-use:
      in.close();

      return lengthFilled;
   }  // method inputFromFile

   /**
    * Writes short integers from the specified
    * subarray to the specified file.
    *
    * @param filename name of output file
    * @param numbers partially-filled array of short
    *                integers
    * @param lengthFilled length of subarray of
    *                <code>numbers</code> containing
    *                the numbers to be output to file
    */
   private static void outputToFile(String fileName,
                                    short[] numbers,
                                    int lengthFilled)
   {
      TextFileOutput out = new TextFileOutput(fileName);

      // Print numbers to output text file buffer:
      for ( int i = 0; i < lengthFilled; i++ )
         out.println(numbers[i]);

      // Make sure the output finds its way to the file:
      out.flush();

      // Release file for re-use:
      out.close();
   }  // method outputToFile
}  // class SortingDemo2