//: Dates.java

/** Simple date calculation program that uses the MyDate class to calculate
  * the number of days between two given dates.
  * @author Mark Crocker <mcrocker@micron.net>
  * @author http://www.markcrocker.com/~mcrocker/
  * @version 0.96
  */

package com.markcrocker.thoughtworks;

import java.io.*;
import java.util.*;
import javax.swing.*;


public class Dates {
    private int debugLevel = 0;  // vestigal 1960s style debugging tool


    /** parseDates.  Converts an array of strings into a MyDate
      *              object.  Input format is VERY fussy.  Expects
      * @param args is a string array of at least three elements.  The elements starting at the indicated index should be MM, DD, YYYY[,] respectively.
      * @param i is the array index where the strings defining the date start.
      * @exception BadDateException via MyDate constructor.
      * @return Initialized MyDate object.
      */
    // May actually be better placed as a constructor in MyDate class.
    private static MyDate parseDates(String[] args, int i) throws BadDateException {
	int year;
	MyDate date = null;
	
	if ((args.length - i > 2) && 
	    (args[i].endsWith(",")) &&
	    (args[i+1].endsWith(",")) ) {  // Need at least three terms, two ending in commas
	    
	    int month = Integer.parseInt(args[i].substring(0,args[i].length()-1));
	    int day   = Integer.parseInt(args[++i].substring(0,args[i].length()-1));
	    
	    if (args[i+1].endsWith(",")) { // Last term may or may not have a comma
		year  = Integer.parseInt(args[++i].substring(0,args[i].length()-1)); // ignore comma
	    } else {
		year  = Integer.parseInt(args[++i].substring(0,args[i].length()));   // no comma
	    }
	    
	    date = new MyDate(year-1900,month,day);
	}
	return date;
    }


    /** parseFile.  Converts a file with pairs of dates on each line
      *             into dates and prints out the number of days
      *             between the two dates.  The date format is VERY fussy.
      *             Each date should be in the format MM, DD, YYYY[,].
      * @param fileName is the file that data data is to be read from.
      * @exception BadDateException via MyDate constructors
      */
    private static void parseFile(String fileName) throws FileNotFoundException, 
                                                          IOException, 
							  BadDateException {
	int debugLevel = 0;  // vestigal 1960s style debugging tool
	StringTokenizer st;
	BufferedReader in = new BufferedReader( new FileReader(fileName));
	String line = new String();
	int lineNo = 0;
	while((line = in.readLine())!= null) {
	    lineNo++;
	    if (debugLevel > 1) { System.out.println ("Line " + lineNo + " is: " + line); }
	    st = new StringTokenizer(line);
       	    String token = st.nextToken();
	    int startMonth = Integer.parseInt(token.substring(0,token.length()-1));
	    token = st.nextToken();
	    int startDay   = Integer.parseInt(token.substring(0,token.length()-1));
	    token = st.nextToken();
	    int startYear  = Integer.parseInt(token.substring(0,token.length()-1));
	    token = st.nextToken();
	    int endMonth   = Integer.parseInt(token.substring(0,token.length()-1));
	    token = st.nextToken();
	    int endDay     = Integer.parseInt(token.substring(0,token.length()-1));
	    token = st.nextToken();
	    int endYear    = Integer.parseInt(token);
		    
	    MyDate startDate = new MyDate(startYear-1900,startMonth,startDay);
	    MyDate endDate = new MyDate(endYear-1900,endMonth,endDay);
	    
	    System.out.println( endDate.between(startDate));
	}
	in.close();
    }


    /** syntaxMessage.  Prints out syntax/help message.
      */
    private static void syntaxMessage() {
	System.out.println("Syntax:\n" +
			   "    Dates MM, DD, YYYY, mm, dd, yyyy\n" +
			   "    Dates -f inputFile\n" +
			   "    Dates [-t|--test|-e|--exceptions|-h|--help]\n" +
			   " Where: MM and mm represent month numbers from 1-12.\n" +
			   "        DD and dd represent day of the month numbers\n" +
			   "          from 1-28, 29, 30 or 31 depending on the month.\n" +
			   "        YYYY and yyyy represent year numbers from 1900-2099, inclusive.\n" +
			   " The first case produces the number of days between the two dates.\n" +
			   " The second case reads dates in the same format as in case on from\n" +
			   "   file inputFile.\n" +
			   " The third case produces test output, exception test output or this message.\n" + 
			   " These switches may be used in combination with each other and multiple times.\n");
    }


    public static void main(String[] args) throws FileNotFoundException, 
                                                  IOException, 
						  BadDateException {
	int debugLevel = 0;  // vestigal 1960s style debugging tool

	if (args.length < 1) {
	    syntaxMessage();
	} else {
	    for (int i = 0; i < args.length; i++) {  // go through all args
		if ( args[i].equals("-t") || 
		     args[i].equals("--test")) {
		    if (debugLevel > 1) { System.out.println("Test mode flag detected"); }
		    System.out.println("Tests passed = " + TestMyDate.testStandardDates());
		} else if ( args[i].equals("-e") || 
			    args[i].equals("--exceptions")) {
		    if (debugLevel > 1) { System.out.println("Exception test mode flag detected"); }
		    TestMyDate.testDateExceptions();
		} else if ( args[i].equals("-h") || 
			    args[i].equals("--help")) {
		    if (debugLevel > 1) { System.out.println("Help mode flag detected"); }
		    syntaxMessage();
		} else if ( (args.length - i > 1) && 
			    (args[i].equals("-f"))  ) {
		    if (debugLevel > 1) { System.out.println("File input from file " + args[i+1] + " requested"); }
		    parseFile(args[++i]);
		} else {
		    MyDate startDate;
		    MyDate endDate;
		    if (((startDate = parseDates(args, i))   != null) && 
			((endDate   = parseDates(args, i+3)) != null))   {
			System.out.println( endDate.between(startDate));
			i += 5;
		    } else { // not a valid input, so spit out a syntax message.
			syntaxMessage();
			break;
		    }
		}
	    }
	}
    }

} ///:~


/* Todo
-------

 1. Command line input:
    a. No input starts GUI.
    b. Switches:
       iii) Debug Level.
 2. More sophisticated input parsing:
    a. Allow for no spaces between fields.
    b. Enforce comma when multiple dates are entered, but not last one.
 4. Deal with 1986 vs. 86 issue.
 5. Add exception catching to parseDates.
 6. Consolodate parsing into a single core routine and share with both parsing methods.
 7. Create GUI version.
 8. Beanify for use in JSP.
 9. Create applet version.
10. Move parseDates to MyDates as a constructor?
11. Change file parser to use StreamTokenizer:
    a. Allows use of comments in input file.

 */