
/*
   This program demonstrates the use of files, streams, exceptions,
   and the network.  It does this by letting the user encode and
   decode files or send and recieve coded messages over the Internet.
   The routines for sending messages over the Internet are written
   as static routines in the class NetworkCodes.

   Two of the possible user commands are currently unimplemented.
   Your lab assignment is to implement them.
*/


import java.io.*;  // Make Java input/output classes available.
import java.net.*; // Make Java networking classes availalble.

public class CodeMain {

   static Console console; // A console Window for input/output.
   static boolean done;    // Set to true when user want's to end the program.

   public static void main(String[] args) {
         // Describe the program to the user, and then use
         // a while loop to process user commands.
         
      console = new Console();

      console.putln("This is a demonstration program that works with");
      console.putln("coded messages, streams, files, and network");
      console.putln("communication.  Encoding and decoding of files");
      console.putln("and messages is based on the use of a \"key word.\"");
      console.putln("A file or message can be dcoded by using the same");
      console.putln("key word that was used to encode it.");

      done = false;  // This will be set to true by the menu() routine
                     //    when the user selects the quit command.

      while (!done) {
         menu();
      }

      console.putln();
      console.putln("OK, quitting...");
      console.close();

   } // end main



   static void menu() {

        // Displays a menu of available operations to the user,
        // reads the user's choice of operation, and carries out
        // the command by calling the appropriate subroutine.
        // If the user's command is "Quit", then the value of 
        // the global variable "done" is set to "true" as a
        // signal to the main() routine that the program should
        // end.

      console.putln();
      console.putln();
      console.putln("What do you want to do?");   // display menu
      console.putln();
      console.putln("        1. Encode a file.");
      console.putln("        2. Decode a file.");
      console.putln("        3. Decode a page from the Internet.");
      console.putln("        4. Send a coded message over the Internet.");
      console.putln("        5. Receive a coded message over the Internet.");
      console.putln("        6. Quit.");
      console.putln();
      console.put("Enter the number of your choice: ");

      int choice = console.getlnInt();   // get user's choice
      console.putln();

      switch (choice) {    // carry out command
          case 1:
             doFile(true);
             break;
          case 2:
             console.putln("Sorry, not implemented.");
             break;
          case 3:
             console.putln("Sorry, not implemented.");
             break;
          case 4:
             NetworkCodedMessage.send(console);
             break;
          case 5:
             NetworkCodedMessage.receive(console);
             break;
          case 6:
             done = true;
             break;
          default:
             console.putln("Illegal input.");
             break;
      }
 
   }  // end menu()


   static void doFile(boolean encode) {

      // If the parameter encode is "true", this routine will encode
      // a file specified by the user.  If the parameter is "false",
      // it will decode the file.  CURRENTLY, ONLY ENCODING IS IMPLEMENTED.
      // The encoded or decoded file is stored in another file, whose
      // name is also specified by the user.
      //    The encoding/decoding operation uses a key word, which is
      // specified by the user.  A file that has been encoded with a
      // key word must be decoded with the same keyword.

      DataInputStream in;  // Stream from reading for the source file.
      PrintStream out;     // Stream for writing to the result file.
      Coder coder;         // An object to do the encoding or decoding.
      String inputLine;    // One line input from the file.
      int lineCt = 0;      // Number of lines from the file that have been processed.


      console.put("Name of source file: ");    // Get input file name,
      String inputFileName = console.getln();  //   and create the input stream.
      try {
         in = new DataInputStream(new FileInputStream(inputFileName));
      }
      catch (IOException e) {
         console.putln("Can't open file " + inputFileName + ".");
         console.putln(e.toString());
         console.putln("Quitting.");
         return;
      }

      console.put("Name of output file: ");    // Get output file name,
      String outputFileName = console.getln(); //   and create the output stream.
      try {
         out = new PrintStream(new FileOutputStream(outputFileName));
      }
      catch (IOException e) {
         console.putln("Can't open file " + outputFileName + ".");
         console.putln(e.toString());
         console.putln("Quitting.");
         return;
      }
      
      console.put("Enter the key word: ");  // Get the keyword and create
      String key = console.getln();         //   the Coder object.
      coder = new Coder(key);

      do {                              // Read a line, encode or decode it,
         try {                          //   and output the result.
            inputLine = in.readLine();
         }
         catch (IOException e) {
            console.putln("An error has occured while inputting data.");
            console.putln(e.toString());
            break;
         }
         if (inputLine != null) {      // A null value indicates end-of-stream.
            String codedLine = coder.encode(inputLine);
            out.println(codedLine);
            lineCt++;
         }
      } while (inputLine != null);

      if (out.checkError()) {  // Print streams don't throw exceptions.
                               // Instead, check for errors with checkError();
         console.putln("Some error has occured while outputting data.");
         console.putln("Output might not be complete.");
      }

      console.putln(lineCt + " lines processed.");

      try {           // It's good form, though not absolutely necessary,
         in.close();  //    to close any files that have been opened.
         out.close();
      }
      catch (IOException e) {
      }

   }  // end of doFile();

 
}  // end of class CodeMain