// ReadNotes.java  P. Conrad, for CISC370, 06/18/2007
//   based on p. 231 from Java Cookbook, 2nd Edition (O'Reilly)

import java.io.*;

import java.util.ArrayList;

public class ReadNotes {

    // the expected number of columns, and the 
    // columns where we can find the various
    // kinds of data
    
    static final String bookPrefix = "JXPC_";
    static final String safariPrefix = "http://safari.oreilly.com/0596003870";

    static final int expectedNumberOfParts = 6;
    
    static final int colSafari = 3;
    static final int colPageNo = 0;
    static final int colChapter = 1;
    static final int colChapterTitle= 2;
    static final int colSection = 4;
    static final int colSectionTitle= 5;
    
    
    ArrayList<Chapter> chapters;

    public static Chapter last(ArrayList<Chapter> al) {
	if (al.size() == 0) 
	    return null;
	else 
	    return al.get(al.size() - 1);
    }
    
    public static Section last(Chapter c) {
	if (c.getNumSections() == 0) 
	    return null;
	else 
	    return c.get(c.getNumSections() - 1);
    }

    public ReadNotes(String filename) {
	
	// set up empty arrays for the chapters and the chapter titles
	
	chapters = new ArrayList<Chapter>();
	
	try {
	    // Based on p. 266 in Java Cookbook, 2nd Edition by O'Reilly
	    // Note: I've changed the code enough now that I could
	    //  probably remove this comment in a later version,
	    //  but I might keep it to help me remember where to
	    //  find more information about reading from files...
	    
	    BufferedReader is = 
		new BufferedReader(new FileReader(filename));	    
	    
	    // skip past header line

	    String inputLine = is.readLine(); 
	    if (inputLine == null) {
		System.err.println("Error: file " + filename +  " is empty");
		System.exit(2);
	    }
	    
	    // read all the rest of the lines from the file and process each one

	    inputLine = is.readLine(); // try to read first line
	    while (inputLine != null) {
		
		processLine(inputLine); // process line if previous read was successful
		
		inputLine = is.readLine(); // try to read next line
	    }
	    
	    is.close();

	} catch (IOException e) {
	    System.out.println("Oopsy Daisy... IOException " + e);
	    System.exit(1);
	} // try/catch
    	
    } // Constructor

   
    public static void main(String args[]) {
	
	if (args.length!=2)
	    {
		System.err.println("Usage: readFile filename outputDir");
		System.exit(1);
	    }

	ReadNotes rn = new ReadNotes(args[0]);

	rn.makeChapterPages(args[1]);

	rn.makeSectionPages(args[1]);

	rn.makeDetailedToc(args[1]);



    } // main 


    void processLine(String inputLine) {
      
	String parts[] = inputLine.split("\t");
	
	
	if (parts.length != expectedNumberOfParts)
	    {
		System.err.println
		    ("Expected " + expectedNumberOfParts + 
		     " columns in input file, but found " 
		     + parts.length);
		System.err.println("Cannot continue.");
		System.exit(2);		
	    }
	
	String thisChapter = parts[colChapter];
	String thisChapterTitle = parts[colChapterTitle];

	String thisSafari = parts[colSafari];
	String thisPageNo = parts[colPageNo];
	String thisSection = parts[colSection];
	String thisSectionTitle = parts[colSectionTitle];


	Section ns = new Section(thisSection,
				 thisSectionTitle,
				 thisPageNo,
				 thisSafari);

	// if this is the very first line in the file,
	// or, if the last chapter on the list doesn't match
	// the chapter on this line of input, then
	// add a new chapter to the list

	Chapter chapter = last(chapters);

	if (chapter == null || 
	    !(chapter.getName().equals(thisChapter)) ) {
	    chapter = new Chapter(thisChapter,thisChapterTitle);
	    chapters.add(chapter);
	}

	// add this section to the chapter.

	chapter.add(ns);

    } // processLine


    public void makeSectionPages (String outputDir) {

	Chapter prevChapter = null;
	Section prevSection = null;
	Chapter nextChapter = null;
	Section nextSection = null;

	for (int chapIndex=0; chapIndex< chapters.size(); chapIndex++) {

	    Chapter c = chapters.get(chapIndex);
	    
	    // print value of c.getName()  in this format 
	    //  ==========
	    //  This_Title
	    //  ==========
	    
	    System.out.println(c.getName().replaceAll(".","="));  
	    System.out.println(c.getName());
	    System.out.println(c.getName().replaceAll(".","=")+"\n");
			       
	    // On each line, output both the previous and the next
	    // sections...
	    
	    
	    
	    for (int sectIndex=0; sectIndex<c.getNumSections(); sectIndex++) {
		Section s = c.get(sectIndex);
		
		// set the pointer to the previous section

		if (chapIndex==0 && sectIndex==0) {
		    prevSection = null;
		} else if (sectIndex == 0) {
		    // if this is the first section, but not the first
		    // chapter, then the previous section is the last
		    // section of the previous chapter
		    prevChapter = chapters.get(chapIndex - 1);
		    prevSection = 
			last(prevChapter);
		} else {
		    prevSection = c.get(sectIndex - 1);
		}
		
		// set the pointer to the next section

		Boolean isLastSection = 
		    (sectIndex  ==  c.getNumSections() - 1);
		Boolean isLastChapter = 
		    (chapIndex  ==  chapters.size() - 1);

		if (isLastChapter && isLastSection) {

		    // if this is the last section of the last chapter,
		    // then there is no next section

		    nextSection = null;

		} else if (isLastSection) {

		    // if this is the last section of this chapter,
		    // but it is NOT the last chapter, then the next section
		    // is the first section of the next chapter.

		    nextChapter = chapters.get(chapIndex + 1);
		    nextSection = nextChapter.get(0);

		} else {
		    // this isn't the last section of this chapter,
		    // so just get the next one.
		    nextSection = c.get(sectIndex + 1);
		}

		// print out a line with the relevant information

		createFile(s,c,prevSection,nextSection,outputDir);

	    }
		
	}
    }


    public void makeChapterPages (String outputDir) {

	Chapter prevChapter = null;
	Section prevSection = null;
	Chapter nextChapter = null;
	Section nextSection = null;

	System.out.println("\n\nMaking chapter indexes...\n\n");

	for (int chapIndex=0; chapIndex< chapters.size(); chapIndex++) {

	    Chapter c = chapters.get(chapIndex);

	    // Set the link to the prevChapter and prevSection, if any

	    if (chapIndex==0) {
		prevChapter = null;
		prevSection = null;
	    } else {
		prevChapter = chapters.get(chapIndex - 1);
		prevSection = last(prevChapter);
	    }


	    // Set the pointer to the next chapter and next section, if any
	    
	    Boolean isLastChapter = 
		(chapIndex  ==  chapters.size() - 1);
	    
	    if (isLastChapter) {
		nextChapter = null;
		nextSection = null;		
	    } else {		
		// if this is the last section of this chapter,
		// but it is NOT the last chapter, then the next section
		// is the first section of the next chapter.
		
		nextChapter = chapters.get(chapIndex + 1);
		nextSection = nextChapter.get(0);
	    }

	    
	    // print value of c.getName()  in this format 
	    //  ==========
	    //  This_Title
	    //  ==========
	    
	    System.out.println("Producing Chapter Index for " + c.getName()
			       + "...");
			       
	    // Open file and write out header information
	    
	    PrintWriter pw = null;

	    try {
		pw = new PrintWriter(outputDir + "/" + chap2wiki(c)
				     + ".txt");


		pw.println("[{ALLOW edit CISC370_07J}]");
		pw.println("\n!!!" + c.getName() + ": " + c.getTitle()) ;

		// This was broken up into multiple print statments to allow
		// easier tracking down of a null pointer exception 
		// happening somewhere in this section of the code

		pw.print("%%commentbox " );
		pw.print("[{InsertPage page='" + bookPrefix +  "_header'}]");

		if (prevChapter!=null) {
		    pw.print("prev: ["); 
		    pw.print((prevChapter==null? "" : prevChapter.getName()));
		    pw.print("|" + chap2wiki(prevChapter) + "]\\\\");
		}

		if (nextChapter!=null) {
		    pw.print("next: [" );
		    pw.print(nextChapter.getName());;
		    pw.print("|" + chap2wiki(nextChapter) + "]\\\\");
		}
		pw.println("%%");	    

	    } catch (Exception e) {
		System.err.println("Exception: " + e);
		e.printStackTrace();
		System.exit(3);
	    }

	    for (int sectIndex=0; sectIndex<c.getNumSections(); sectIndex++) {

		Section s = c.get(sectIndex);
		// print the information for this section

		pw.println
		    ("|" + s.getName() + "|" + s.getTitle() 
		     + "|[" + sect2page(s) + "|" + sect2wiki(s) 
		     + "]|[safari|" + sect2safari(s) 
		     + "]");
		
	    } // for loop over sections




	    
	    // finish up this chapter file 

	    try {
		pw.println("----");
		pw.println("[{InsertPage page='" + bookPrefix + "_footer'}]");
		pw.close();
	    } catch (Exception e) {
		System.err.println("Exception: " + e);
		e.printStackTrace();
		System.exit(3);
	    }

		
	} // for loop over chapters
    }

    public void makeDetailedToc (String outputDir) {

	Chapter prevChapter = null;
	Section prevSection = null;
	Chapter nextChapter = null;
	Section nextSection = null;


	String filename = bookPrefix + "_detailed_toc.txt";

	System.out.println("\n\nMaking detailed toc...\n\n");

	
	// Open file and write out header information
	
	PrintWriter pw = null;
	
	try {
	    pw = new PrintWriter(outputDir + "/" + filename);


	    pw.println("[{ALLOW edit CISC370_07J}]");
	    pw.println("\n!!! Head First Java (Detailed Table of Contents)");

	    // This was broken up into multiple print statments to allow
	    // easier tracking down of a null pointer exception 
	    // happening somewhere in this section of the code
	    
	    pw.print("%%commentbox [{InsertPage page='" + bookPrefix+  "_header'}]%%");

	    } catch (Exception e) {
		System.err.println("Exception: " + e);
		e.printStackTrace();
		System.exit(3);
	    }
	
	
	for (int chapIndex=0; chapIndex< chapters.size(); chapIndex++) {
	    
	    Chapter c = chapters.get(chapIndex);
	    
	    pw.println("\n! [" + c.getName() 
		       + "|" + chap2wiki(c) + "]: " + c.getTitle() + "\n");
	    
	    for (int sectIndex=0; sectIndex<c.getNumSections(); sectIndex++) {
		
		Section s = c.get(sectIndex);
		// print the information for this section

		pw.println
		    ("|" + s.getName() + "|" + s.getTitle() 
		     + "|[" + sect2page(s) + "|" + sect2wiki(s) 
		     + "]|[safari|" + sect2safari(s) 
		     + "]");
		
	    } // for loop over sections

	    
		
	} // for loop over chapters

	// finish up the detailed toc file
	
	try {
	    pw.println("----");
	    pw.println("[{InsertPage page='" + bookPrefix + "_footer'}]");
	    pw.close();
	} catch (Exception e) {
	    System.err.println("Exception: " + e);
	    e.printStackTrace();
	    System.exit(3);
	}
	

    } // makeDetailedToc



    /**
     * Convert a Section reference to a string such as p345
     */
    
    public String sect2page(Section s) {
	
	return ((s==null) ? "" : "p" + s.getPage());
    }

    /**
     * Convert a Section reference to a safari node URL such as 
     * "http://safari.oreilly.com/0596009208/hfjava2-CHP-1-SECT-1"
     * The first part comes from the safariPrefix constant.
     */

    public String sect2safari(Section s) {
	return ((s==null) ? "" : safariPrefix + "/" + s.getSafari());
    }

    /**
     * Convert a Section reference to a wiki page name such as HFJ_p345
     * The HFJ part comes from the bookPrefix constant (e.g. "HFJ_").
     */

    public String sect2wiki(Section s) {
	return ((s==null)? "" : bookPrefix + sect2page(s));
    }


    /**
     * Convert a Chapter reference to a wiki page name such as HFJ_Chapter1
     * The HFJ part comes from the bookPrefix constant (e.g. "HFJ_").
     */

    public String chap2wiki(Chapter c) {
	return ((c==null)? "" : bookPrefix + c.getName().replaceAll(" ",""));
    }


    /**
     * Convert a Chapter reference to the chapter name.
     * Conver to blanks if the reference is null.
     */

    public String chap2name (Chapter c) {
	return ((c==null)? "" : c.getName());
    }

    /**
     * Convert a Chapter reference to the chapter title.
     * Conver to blanks if the reference is null.
     */

    public String chap2title (Chapter c) {
	return ((c==null)? "" : c.getTitle());
    }

    /**
     * Convert a Section reference to the section name.
     * Conver to blanks if the reference is null.
     */

    public String sect2name (Section s) {
	return ((s==null)? "" : s.getName());
    }

    /**
     * Convert a Section reference to the section title.
     * Conver to blanks if the reference is null.
     */

    public String sect2title (Section s) {
	return ((s==null)? "" : s.getTitle());
    }

 
    /**
   * create a file containing wiki markup for this section, with
   * links to the prev and next sections.  Store it in the directory
   * referred to by outputDir
   */
 
    public void createFile(Section curr,  
			   Chapter c,
			   Section prev, Section next,
			   String outputDir) {

	try {
	    PrintWriter pw = 
		new PrintWriter(outputDir + "/" + sect2wiki(curr) + ".txt");
	    
	    pw.println("[{ALLOW edit CISC370_07J}]");
	    pw.print
		("%%commentbox " );
	    pw.print("[{InsertPage page='" + bookPrefix +  "_header'}]");

	    if (prev!=null) {
		pw.print("prev: [" + sect2wiki(prev) + "|" + sect2wiki(prev) + "]\\\\");
	    }

	    pw.print("curr: [safari|" + sect2safari(curr) + "]\\\\");

	    if (next!=null){
		pw.print
		    ("next: [" 
		     + sect2wiki(next) + "|" + sect2wiki(next) + "]\\\\");
	    }

	    pw.println("%%");

	    pw.println("\n!!!" + curr.getName() + ": " + curr.getTitle() + " %%(font-size: smaller) (" + bookPrefix.replaceAll("_"," ") + "p. " 
		       + curr.getPage() + ")%%");

	    pw.println("\n");



	    pw.println("!! Instructor's Notes\n\n");	    	   
	    pw.println("@@@ Fill in Instructor's Notes here.@@@\n");
	    pw.println("@@@Remove these lines once you've started filling in notes. @@@\n\n");

	    pw.println("!! Notes by Students\n\n");
	    pw.println("@@@ Students, fill in notes here.@@@\n");
	    pw.println("@@@Remove these lines once you've started filling in notes. @@@\n\n");
	    
	    pw.println("----\n");

	    pw.println("! [" + c.getName() 
		       + "|" + chap2wiki(c) + "]: " + c.getTitle());

	    if (prev!=null) {
		pw.println
		    ("|[prev|" + sect2wiki(prev)+ "]|" + sect2title(prev) 
		     + " (p. " + prev.getPage() + ")"); 
	    }
	    
	    pw.println("|curr|" + sect2title(curr) 
		       + "(p. " + curr.getPage() + ")");
	    
	    if (next!=null) {
		
		pw.println
		    ("|[next|" + sect2wiki(next) + "]|" + sect2title(next)
		     + " (p. " + next.getPage() + ")");

	    }
	    
	    pw.println("----");
	    
	    pw.println("[{InsertPage page='" + bookPrefix + "_footer'}]");	    

	    pw.close();
	} catch (Exception e) {
	    System.err.println("Exception: " + e);
	    e.printStackTrace();
	    System.exit(3);
	}
	

    } // createFile

} // class
