
/* 0123456789012345678901234567890123456789012345678901234567890123456789789 */

/*
 * cd_create.java
 *
 * This file is part of cd_create.
 *
 * cd_create is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * cd_create is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cd_create; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Copyright 2004 Abi Arroyo
 */

/*
 * Potential features to add:
 * - DONE: Loading saved configuration values from a file (.edcrc)
 * - DONE: Run application in "quiet mode"
 * - DONE: Include md5 data on CD
 * - DONE: Restructure CDCase constructor to change when temporary directory is created
 * - DONE: When we reset the CDCase, we lose our loaded settings
 * - DONE: help menu for command line argument
 * - verify multisession support
 * 
 */

import java.io.*;
import java.util.*;

public class cd_create {

   static String input;
   static String edcrc;
   static BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
   static CDCase library;
	static boolean verbose = false;

   public static void main (String[] args) {

      /*
       * ---------------------------------------------------------------------
       * Search for and load configuration file
       * ---------------------------------------------------------------------
       *
       */

		int idx = 0;
		edcrc = "";

		if (args.length > 0) {
			if (args[idx].compareToIgnoreCase("-c") == 0) {

			   edcrc = args[++idx];
				idx++;
				
			   if ((args.length > idx) && (args[idx].compareToIgnoreCase("-v") == 0)) {
				   verbose = true;
				   idx++;
				}
			}
			else if (args[idx].compareToIgnoreCase("-v") == 0) {

				verbose = true;
				idx++;

			   if ((args.length > idx) && (args[idx].compareToIgnoreCase("-c") == 0)) {
			      edcrc = args[++idx];
					idx++;
			   }

			}
			else if ((args[idx].compareToIgnoreCase("-h") == 0) ||
			        (args[idx].compareToIgnoreCase("--help") == 0) ||
			        (args[idx].compareToIgnoreCase("-help") == 0)) {

                    System.out.println("\n" + CDCase.version + " by Abi Arroyo (abi@e-arroyo.net)");
						  System.out.println("\ncd_create [ -h | -v | -c config_file ] file1 ... fileN");
						  System.out.println("\n\t-h\t\tPrints this help text");
						  System.out.println("\t-v\t\tIncreases the verbosity of the application");
						  System.out.println("\t-c config_file\tSpecify the configuration file to use\n");

						  return;
		  }
		}

		if (edcrc.length() <= 0) {
			try {
			   int i = 0;
			   String[] check = {
				                   (new File(".")).getCanonicalPath() + File.separator + ".edcrc",
				                   "/etc/.edcrc"
				                 };

			   do {
				   if (new File(check[i]).canRead()) {
					   edcrc = check[i];
				   	break;
				   }
			   } while (++i < check.length);
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}

		if (edcrc.length() <= 0) {
			System.out.println(CDCase.version + ": unable to find configuration file");
		   return;
		}

      if (!init_cd_create()) {
			System.out.println(CDCase.version + ": error initializing cd_create");
			return;
		}

      /*
       * ---------------------------------------------------------------------
       * Run in batch mode
       * ---------------------------------------------------------------------
       *
       */

		boolean added;

      if (((args.length-idx) > 0) && (args.length > 0)) {

			do {
				added = library.add (args[idx]);
				if (verbose) {
					if (added)
			         System.out.println(" * File successfully added to list: " + args[idx]);
			      else 
			         System.out.println(" ! Unable to add file to list: " + args[idx]);
				}
	      } while (++idx < args.length);

			if (library.compile()) {
            library.burn(-1);
			}

	      return;

      }

      /*
       * ---------------------------------------------------------------------
       * Run interactive mode
       * ---------------------------------------------------------------------
       *
       */


      // Simple menu depicting the functionality of a CDCase
      while (true) {
 
         System.out.println("\n. ..  ...   ....    .....     ......      .......       ........");
         System.out.println("                        |                      |               $");
         System.out.println("     Stage 1            |    Stage 2           |  Stage 3      $");
         System.out.println("                        |                      |               $");
         System.out.println(". ..  ...   ....    .....     ......      .......       ........");
         System.out.println("                        |                      |               $");
         System.out.println("                        |                      |               $");
         System.out.println("  1. Add file           | 5. Create CD         | 15. Burn      $");
         System.out.println("  2. Remove file        | 6. Remove CD         | 20. Save      $");
         System.out.println("  3. Print pre-list     | 7. Clear CD          | 21. Load      $");
         System.out.println("  4. Compile            | 8. Search CDCase     | 22. Reset     $");
         System.out.println("                        | 10. Print CDCase     | 99. Exit      $");
         System.out.println("                        |                      |               $");
         System.out.println(". ..  ...   ....    .....     ......      .......       .......'");
         
         System.out.print("\n> ");

         try {
            input = in.readLine();

            System.out.println();

            switch (Integer.parseInt(input)) {

               case 1:

                  do {
				      
				         System.out.print("Enter the full path of a directory or file to add> ");
				         input = in.readLine();
				         System.out.println("Attempting to add file: " + input);
				         
				         if (library.add (input))
				            System.out.println(" * File successfully added to list: " + input);
				         else 
				            System.out.println(" ! Unable to add file to list: " + input);
				      
				      } while (input.length() > 0);
				  
				      break;

               case 2:

                  do {
				      
				         System.out.print("Enter the full path of a directory or file to remove> ");
				         input = in.readLine();
				         System.out.println("Attempting to remove file: " + input);
				         
				         if (library.remove (input))
					         System.out.println(" * File successfully added to list: " + input);
				         else 
					         System.out.println(" ! Unable to add file to list: " + input);
				   
				      } while (input.length() > 0);
				   
				      break;                  

               case 3:
                  
                  library.printPreList();
                  break;
               
               case 4:
               
                  library.compile();
                  break;
                  
               case 5:
			         
			         library.createCD();
			         break;
			         
               case 6:
			      
			         System.out.print("Enter CD number to remove> " );
				      input = in.readLine();
				      
				      if (library.removeCD(Integer.parseInt(input)))
				         System.out.println(" * CD successfully removed from CDCase.");
				      else
				         System.out.println(" ! Error removing CD.");
				      
				      break;
				      
               case 7:
			         
			         System.out.print("Enter CD number to clear> " );
			         input = in.readLine();
			         
			         if (library.removeCD(Integer.parseInt(input)))
				         System.out.println(" * CD successfully cleared from CDCase.");
			         else
				         System.out.println(" ! Error clearing CD.");
			         
			         break;
			         
			      case 8:
			      
			         System.out.print("Enter search pattern> ");
			         input = in.readLine();
			         System.out.println("Searching archive for regular expression: " + input);

   			      int i,j; 
			         LinkedList[] results = library.search(input);
			         LinkedList perCD;
                  
			         if (results != null) {
				         for (i = 0; i < results.length; i++) {
					         perCD = results[i];
					    
					         if (perCD != null) {
						         for (j = 0; j < perCD.size(); j++) 
						            System.out.println("cd " + i + ": num " + j + ") " + (perCD.get(j)).toString());
					        }
				        }
			         }
			         
                  break;
               
			         // be able to select which files to remove after performing search...		      
               
               case 9:
                  
            
               case 10:
			      
			         library.printCDCase();
			         break;
			      
			      case 12:
			           
			         System.out.print("Enter file to remove> ");
			         input = in.readLine();
			         System.out.println("Attempting to remove file: " + input);
			            
			         if (library.remove (input, -1))
				         System.out.println(" * File successfuly removed CDCase: " + input);
			         else 
				        System.out.println(" ! Unable to remove file from CDCase: " + input);
			   	      
			   	   break;
			         
			      case 15:
			            
			         library.burn(-1);
			         break;
			         
			      case 20:
				   
				      System.out.print("Enter name of CDCase with full path to save> " );
				      input = in.readLine();
                  
                  if (library.save(input))
                     System.out.println(" * CDCase saved successfully.");
                  else
                     System.out.println(" ! Error saving CDCase.");
                  break;
                  
               case 21:
				         
				      System.out.print("Enter of saved CDCase to load with full path> ");
				      input = in.readLine();
				         
				      if (library.load(input, true))
				         System.out.println(" * CDCase successfully load.");
				      else
				         System.out.println(" ! Error loading CDCase.");
				         
				      break;
				   
				   case 22:
               
                   if (!init_cd_create()) {
			             System.out.println(CDCase.version + ": error initializing cd_create");
							 return;
						 }
						 
                   break;
                  
               case 99:
                  
                  // perform clean-up
                  library.close();
                  return;
                     
               default:
                     
                  System.out.println(" ! Invalid selection.");
                  break;
                     
            } 
         }
            
         catch (IOException e) {
         }
         catch (NumberFormatException e) {
            System.err.println("Oops!");
         }
      }

   } 

   /*
    * ---------------------------------------------------------------------
    * cd_create interface initialization
    * ---------------------------------------------------------------------
    *
    */

	private static boolean init_cd_create () {

		File f = new File (edcrc);

		if (!f.canRead())
	      return false;

		try {

         StringTokenizer st;
		   String ident, value, line, theDir;
         BufferedReader someFile = new BufferedReader (new FileReader(edcrc));

			// in regards to settings a temporary directory, we do not need to setup
			// the object to set these values since they are all static variables.
			// however, it needs to be ensured that the underlying classes do not modify
			// the values later.
			
         while ((line = someFile.readLine()) != null) {

				// System.out.println(line);

			   if ((line.trim().length() > 0) && (line.trim().charAt(0) != '#')) {

   			   st = new StringTokenizer(line, "!");
			      ident = st.nextToken().trim();
			      value = st.nextToken().trim();
				
				   if (ident.charAt(0) != '#') {

						if (ident.compareToIgnoreCase("temp") == 0) {
							library = new CDCase(value);
					   }
						else if (ident.compareToIgnoreCase("cdrecord") == 0) {
						   CD.cdrecord_path = value;
					   }
						else if (ident.compareToIgnoreCase("cdrecord_opts") == 0) {
						   CD.cdrecord_opts = " " + value + " ";
					   }
						else if (ident.compareToIgnoreCase("cdrecord_scanbus") == 0) {
						   CD.cdrecord_scanbus = " " + value + " ";
					   }
						else if (ident.compareToIgnoreCase("mkisofs") == 0) {
						   CD.mkisofs_path = value;
					   }
						else if (ident.compareToIgnoreCase("md5") == 0) {
						   verify.md5_file = value;
					   }
						else if (ident.compareToIgnoreCase("mkisofs_opts") == 0) {
						   CD.mkisofs_opts = " " + value + " ";
					   }
						else if (ident.compareToIgnoreCase("loglevel") == 0) {
						   CDCase.logLevel = Integer.parseInt (value);
					   }
						else if (ident.compareToIgnoreCase("cd") == 0) {
						   CDCase.cdPath = value;
					   }
						else if (ident.compareToIgnoreCase("cdsize") == 0) {
							CDCase.MAX_CD_SIZE = Integer.parseInt (value);
					   }
						else if (ident.compareToIgnoreCase("continuity") == 0) {
						   CDCase.keepContinuous = value.matches("true");
					   }
						else if (ident.compareToIgnoreCase("verifydata") == 0) {
						   CDCase.verifyData = value.matches("true");
						}
						else if (ident.compareToIgnoreCase("stoponfailure") == 0) {
						   CDCase.stopOnFailure = value.matches("true");
						}
						else if (ident.compareToIgnoreCase("addbigfirst") == 0) {
						   CDCase.addBigFirst = value.matches("true");
						}

				   }
				}
			} // end while

		} // end try

		catch (IOException e) {
			e.printStackTrace();
		}

		// perform some simple verification
		f = new File (CD.mkisofs_path);

		if (!f.exists()) {
	      System.out.println (CDCase.version + "Unable to find mkisofs: " + CD.mkisofs_path);
			return false;
		}

		f = new File (CD.cdrecord_path);

		if (!f.exists()) {
	      System.out.println (CDCase.version + "Unable to find cdrecord: " + CD.cdrecord_path);
			return false;
		}

		f = new File (verify.md5_file);

		if (!f.exists()) {
	      System.out.println (CDCase.version + "Unable to find md5deep: " + verify.md5_file);
			return false;
		}

      System.out.println("\n" + CDCase.version + " by Abi Arroyo (abi@e-arroyo.net)");

		if (verbose) printSettings();

		return true;
	}

	private static void printSettings () {

		System.out.println("\n================================================================================");
		System.out.println("config file:		" + edcrc);
		System.out.println("temporary directory:	" + CDCase.tempDir);
		System.out.println("logging level:		" + CDCase.logLevel);
		System.out.println("\ncdrecord:		" + CD.cdrecord_path);
		System.out.println("cdrecord options:	" + CD.cdrecord_opts);
		System.out.println("mkisofs:		" + CD.mkisofs_path);
		System.out.println("mkisofs options:	" + CD.mkisofs_opts);
		System.out.println("md5deep:		" + verify.md5_file);
      System.out.println("\nCD-ROM location:	" + CDCase.cdPath);
      System.out.println("Maximum CD size:	" + CDCase.MAX_CD_SIZE + " bytes");
      System.out.println("Stop on Failure:	" + CDCase.stopOnFailure);
      System.out.println("Verify Data:		" + CDCase.verifyData);
      System.out.println("Continuous:		" + CDCase.keepContinuous);
      System.out.println("Add Big First:		" + CDCase.addBigFirst);
		System.out.println("================================================================================");

		// stop on failure, verify data, keep continuous, add big first
	}

}
