/* DVDCollection.java        Authors: Koffman & Wolz
 * Class that stores a collection of DVDs.
 * Uses FileReader, BufferedReader,
 * FileWriter, PrintWriter,
 * DataOutputStream, DataInputStream.
 */
import javax.swing.*;
import java.io.*;
import java.util.*;

public class DVDCollection {
   // Data field
   Vector DVDs = new Vector();

   // Methods
   // postcondition: Writes the DVD information stored in vector DVDs
   //   to binary object file outs.
   public void writeDVDBinaryObjectFile(ObjectOutputStream outs) {
      try {
         // Write each DVD to binary object file outs.
         for (int next = 0; next < DVDs.size(); next++) {
            DVD nextDVD = (DVD) DVDs.elementAt(next);
            nextDVD.writeDVD(outs);
         }

         outs.close();
      }
      catch (IOException e) {
         System.out.println("i/o error: " + e.getMessage());
         e.printStackTrace();
      }
   }

   // postcondition: Reads a collection of DVDs from binary object
   //   file ins and stores the information in vector DVDs.
   public void readDVDBinaryObjectFile(ObjectInputStream ins) {
      try {
         // Read data for DVD collection and store it in DVDs.
         try {
            while (true) {
               DVD aDVD = new DVD();
               aDVD.readDVD(ins);
               DVDs.addElement(aDVD);
            }
         }
         catch (EOFException eof) {
            System.out.println("end of input file reached");
            ins.close();
         }
      }  // Catch errors
      catch (IOException ex) {
         System.out.println("i/o error: " + ex.getMessage());
         ex.printStackTrace();
      }
      catch (ClassNotFoundException ex) {
         System.out.println(ex.getMessage());
         ex.printStackTrace();
      }
   }

   // postcondition: Writes the DVD information
   //   to binary file outs.
   public void writeDVDBinaryFile(DataOutputStream outs) {
      try {
         // Write each DVD to binary file outs.
         for (int next = 0; next < DVDs.size(); next++) {
            DVD nextDVD = (DVD) DVDs.elementAt(next);
            nextDVD.writeDVD(outs);
         }

         outs.close();
      } catch (IOException ex) {
         System.out.println("i/o error" + ex.getMessage());
         ex.printStackTrace();
      }
   }

   // postcondition: Reads a collection of DVDs from binary file ins
   //   and stores the information in vector DVDs.
   public void readDVDBinaryFile(DataInputStream ins) {
      try {
         // Read data for DVD collection and store it in DVDs.
         try {
            while (true) {
               DVD aDVD = new DVD();
               aDVD.readDVD(ins);
               DVDs.addElement(aDVD);
            }
         }  catch (EOFException eof) {
            System.out.println("end of input file reached");
            ins.close();
         }
      } catch (IOException ex) {
         System.out.println("i/o error: " + ex.getMessage());
         ex.printStackTrace();
      }
   }

   // postcondition: Reads all data from specified input file into
   //   vector DVDs. Throws a FileNotFoundException
   //   if input file is missing.
   public void readDVDs(BufferedReader ins) {
      try {
        // Read and store data for DVD collection
        String title = ins.readLine();
        while (title != null) {
           String category = ins.readLine();
           int year = Integer.parseInt(ins.readLine());
           double cost = Double.parseDouble(ins.readLine());
           DVDs.addElement(new DVD(title, category, year, cost));
           title = ins.readLine();
        }
        ins.close();
      } // catch or throw exceptions
      catch (NumberFormatException ex) {
        System.out.println("bad numeric string");
        ex.printStackTrace();
      }
      catch (IOException ex) {
        System.out.println("i/o error " + ex.getMessage());
        ex.printStackTrace();
      }
   }

   // precondition: Vector DVDs stores a DVD collection
   // postconditon: Writes the collection to the specified file.
   public void writeDVDs(PrintWriter outs) {
      // Write the DVD collection to the output file
      for (int next = 0; next < DVDs.size(); next++) {
         DVD nextDVD = (DVD) DVDs.elementAt(next);
         outs.println(nextDVD.getTitle());
         outs.println(nextDVD.getCategory());
         outs.println(nextDVD.getYear());
         outs.println(nextDVD.getTime());
      }

      outs.close();
      System.out.println("Output file written");
   }

   // postcondition: Adds the specified DVD to the collection.
   public void addDVD(DVD aDVD) {
      DVDs.addElement(aDVD);
   }

   // postcondition; Returns a string of all DVD titles
   //   in a specified category.
   public String listInCategory(String targetCat) {
      String result = "";
      for (int next = 0; next < DVDs.size(); next ++) {
        DVD nextDVD = (DVD) DVDs.elementAt(next);
        if (nextDVD.getCategory().equals(targetCat))
           result += nextDVD.getTitle() + "\n";
      }
      return result;
   }

   // postcondition: Returns the DVD with a specified title.
   //   Returns a null reference if not found.
   public DVD searchDVD(String aTitle) {
      for (int next = 0; next < DVDs.size(); next ++) {
         DVD nextDVD = (DVD) DVDs.elementAt(next);
         if (nextDVD.getTitle().equals(aTitle))
           return nextDVD;
       }

       // Assertion: DVD with aTitle not found.
       return null;
   }

   // postcondition: Represents the collection as a string.
   public String toString() {
      return DVDs.toString();
   }

   // Driver program to test binary file input and output.
   // postcondition: Reads DVD data from text file,
   //   writes it to binary output file, and then reads the binary file.
   public static void main(String[] args) {
      try {
        DVDCollection myDVDs = new DVDCollection();

        // Create object ins and connect it to the input file
        String inFileName =
             JOptionPane.showInputDialog("Enter input file name");
        FileReader inStream = new FileReader(inFileName);
        BufferedReader ins = new BufferedReader(inStream);

        // Read DVD collection
        myDVDs.readDVDs(ins);
        System.out.println(myDVDs.toString());

        // Create object outs and associate it with the output file.
        String outFileName =
             JOptionPane.showInputDialog("Enter output file name");
        FileOutputStream outStream = new FileOutputStream(outFileName);
        ObjectOutputStream outs = new ObjectOutputStream(outStream);

        // Write DVD collection to file outs.
        myDVDs.writeDVDBinaryObjectFile(outs);

        // Create object bins and connect it to the input file
        //   (the binary output file written above)
        FileInputStream binStream = new FileInputStream(outFileName);
        ObjectInputStream bins = new ObjectInputStream(binStream);

        // Read DVD collection from binary input file.
        myDVDs = new DVDCollection();
        myDVDs.readDVDBinaryObjectFile(bins);
     
        System.out.println(myDVDs.toString());
     }  catch (IOException ex) {
        System.out.println(ex.getMessage());
     }
  }
}
