/*
 * Created on 03.08.2004 11:02:21
 *
 * Multimediale Algorithmen und Datenstrukturen Assessments
 */
package help;

import javax.swing.*;

import java.awt.*;
import java.io.IOException;
import java.net.URL;
import java.util.Vector;

import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.tree.TreePath;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;

/**
 * Provides a tree-view of the titles of the help-pages.
 * 
 * @author Markus Krebs
 */
public class HelpTree implements TreeSelectionListener {
	
	private static boolean DEBUG = false;
	
	/**
	 * Show the whole available help.
	 */
	public static final int COMPLETE_VIEW = 0;
	
	/**
	 * Show a GenEditor-specific help.
	 */
	public static final int GENEDITOR_VIEW = 1;
	/**
	 * Show a WorkEditor-specific help.
	 */
	public static final int WORKEDITOR_VIEW = 2;
	/**
	 * Show a EvalEditor-specific help.
	 */
	public static final int EVALEDITOR_VIEW = 3;
	/**
	 * Show a EvalPlayer-specific help.
	 */
	public static final int EVALPLAYER_VIEW = 4;
	
	private static boolean SHOW_GENEDITOR = true;
	private static boolean SHOW_WORKEDITOR = true;
	private static boolean SHOW_EVALEDITOR = true;
	private static boolean SHOW_EVALPLAYER = true;

	private JPanel panel;
	
	private JTree tree;
	private JEditorPane htmlPane;

	// History
	private boolean nextNoHistoryEntry;
	private int position;
	private Vector history;

	/**
	 * Creates a new Help-Tree in respect to <code>setView(int)</code> specified view.
	 * @param editorPane The EditorPane for the to displayed content.
	 * @see HelpTree#setView(int)
	 */
	public HelpTree(JEditorPane editorPane) {
		htmlPane = editorPane;
		
		panel = new JPanel();
		panel.setLayout(new BorderLayout());
		
		tree = new JTree(createTree());
		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		tree.addTreeSelectionListener(this);

		panel.add(tree, BorderLayout.CENTER);
		
		// Für History
		history = new Vector();
		position = -1;
		nextNoHistoryEntry = false;
		
		// Muss nach History-Initialisierung stehen
		tree.setSelectionRow(0);
	}

	/* (non-Javadoc)
	 * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
	 */
	public void valueChanged(TreeSelectionEvent e) {
    	DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
    	nodeClicked(node);
	}

    private void nodeClicked(DefaultMutableTreeNode node) {
    	if (node == null) return;
    	
    	//tree.setSelectionPath();
    	
    	Object nodeInfo = node.getUserObject();
    	//if (node.isLeaf()) {
    	HelpInfo helpInfo = (HelpInfo)nodeInfo;
    	displayURL(helpInfo.getURL());
    	
    	urlClicked(helpInfo.getURL());
    	
    	if (DEBUG) {
    		System.out.print(helpInfo.getURL() + ":  \n    ");
    	}
    	//} else {
    	//	displayURL(helpURL); 
    	//}
    	if (DEBUG) {
    		System.out.println(nodeInfo.toString());
    	}
	}
	private void displayURL(URL url) {
		try {
			if (url != null) {
				htmlPane.setPage(url);
			} else { //null url
				htmlPane.setText("File Not Found");
				if (DEBUG) {
					System.out.println("Attempted to display a null URL.");
				}
			}
		} catch (IOException e) {
			System.err.println("Attempted to read a bad URL: " + url);
		}
	}
	
	/**
	 * Returns a panel that contains the Tree.
	 * @return The panel.
	 */
	public JPanel getPanel() {
		return panel;
	}
	/**
	 * Tests if a backward-step (undo) is possible
	 * @return true if possible, false otherwise
	 */
	public boolean canUndo() { return position>0; }
	/**
	 * Tests if a forward-step (redo) is possible
	 * @return true if possible, false otherwise
	 */
	public boolean canRedo() { return position<history.size()-1; }
	
	// History-Eintrag
	private void urlClicked(URL url) {
		if(nextNoHistoryEntry) {
			nextNoHistoryEntry = false;
			return;
		}
		position++;
		while (history.size() > position) history.removeElementAt(position);
		history.add(tree.getSelectionPath());
	}
	/**
	 * Go in history one step backward.
	 */
	public void undo() {
		if(!canUndo()) return;
		position--;
		nextNoHistoryEntry = true;
		TreePath tp = (TreePath)history.elementAt(position);
		tree.setSelectionPath(tp);
		tree.scrollPathToVisible(tp);
	}
	/**
	 * Go in history one step forward.
	 */
	public void redo() {
		if(!canRedo()) return;
		position++;
		nextNoHistoryEntry = true;
		TreePath tp = (TreePath)history.elementAt(position);
		tree.setSelectionPath(tp);
		tree.scrollPathToVisible(tp);
	}
	/**
	 * Go one step backward in the documentation
	 */
	public void back() {
    	DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
    	node = node.getPreviousNode();
    	if(node==null) return;
    	TreePath tp = new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(node));
    	tree.setSelectionPath(tp);
    	tree.scrollPathToVisible(tp);
	}
	/**
	 * Go one step forward in the documentation
	 */
	public void forward() {
    	DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
    	node = node.getNextNode();
    	if(node==null) return;
    	TreePath tp = new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(node));
    	tree.setSelectionPath(tp);
    	tree.scrollPathToVisible(tp);
	}
	// Ansicht des Baumes setzen (Teile ausblenden)
	/**
	 * Sets the display-mode of the help-system.
	 * @param id The ID for the VIEW.
	 * @see HelpTree#COMPLETE_VIEW
	 * @see HelpTree#GENEDITOR_VIEW
	 * @see HelpTree#WORKEDITOR_VIEW
	 * @see HelpTree#EVALEDITOR_VIEW
	 * @see HelpTree#EVALPLAYER_VIEW
	 */
	public static void setView(int id) {
		if(id == COMPLETE_VIEW) {
			SHOW_GENEDITOR = true;
			SHOW_WORKEDITOR = true;
			SHOW_EVALEDITOR = true;
			SHOW_EVALPLAYER = true;
			return;
		}
		SHOW_GENEDITOR = false;
		SHOW_WORKEDITOR = false;
		SHOW_EVALEDITOR = false;
		SHOW_EVALPLAYER = false;
		switch(id) {
			case GENEDITOR_VIEW : SHOW_GENEDITOR = true; break;
			case WORKEDITOR_VIEW : SHOW_WORKEDITOR = true; break;
			case EVALEDITOR_VIEW : SHOW_EVALEDITOR = true; break;
			case EVALPLAYER_VIEW : SHOW_EVALPLAYER = true; break;
		}
	}
	
	/**
	 * Creates the tree in respect to the defined view
	 * @return Root-Node
	 * @see HelpTree.setView(int)
	 */
	private DefaultMutableTreeNode createTree() {
		DefaultMutableTreeNode top = null;
		DefaultMutableTreeNode cat1 = null;
		DefaultMutableTreeNode cat2 = null;
		DefaultMutableTreeNode cat3 = null;
		
		top = new DefaultMutableTreeNode(new HelpInfo("MA & DA", "main.html"));

		// Einführung
		
		cat1 = new DefaultMutableTreeNode(new HelpInfo("Einführung", "introduction/main.html"));
		top.add(cat1);

		cat2 = new DefaultMutableTreeNode(new HelpInfo("Operationen & Teiloperationen", "introduction/opasubop/main.html"));
		cat1.add(cat2);

		cat3 = new DefaultMutableTreeNode(new HelpInfo("Fibonacci-Heap", "introduction/opasubop/fibheap.html"));
		cat2.add(cat3);
		cat3 = new DefaultMutableTreeNode(new HelpInfo("Binomial-Queue", "introduction/opasubop/binqueue.html"));
		cat2.add(cat3);
		
		cat2 = new DefaultMutableTreeNode(new HelpInfo("Interaktion", "introduction/interaction.html"));
		cat1.add(cat2);

		// GenEditor
		if(SHOW_GENEDITOR) {
			cat1 = new DefaultMutableTreeNode(new HelpInfo("GenEditor", "geneditor/main.html"));
			top.add(cat1);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Interaktion", "geneditor/interaction/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Fibonacci-Heap", "geneditor/interaction/fibheap.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Binomial-Queue", "geneditor/interaction/binqueue.html"));
			cat2.add(cat3);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Die Reiter", "geneditor/tabs/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Exercise", "geneditor/tabs/exercise.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Operations", "geneditor/tabs/operations.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Ratings", "geneditor/tabs/ratings.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("1st Init", "geneditor/tabs/1stinit.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("2nd Scramble", "geneditor/tabs/2ndscramble.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("3rd AutoGen", "geneditor/tabs/3rdautogen.html"));
			cat2.add(cat3);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Aufgabenerstellung", "geneditor/exercisecreation/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Normal-Mode", "geneditor/exercisecreation/normalmode.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Fault-Mode", "geneditor/exercisecreation/faultmode.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Automatische Generierung", "geneditor/exercisecreation/automatic.html"));
			cat2.add(cat3);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Wechseln des PlugIns", "geneditor/changeplugin.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Speichern von Aufgaben", "geneditor/saveexercise.html"));
			cat1.add(cat2);
		}

		// AutoGenerator
		if(SHOW_GENEDITOR) {
			cat1 = new DefaultMutableTreeNode(new HelpInfo("AutoGenerator", "autogenerator/main.html"));
			top.add(cat1);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Parameter", "autogenerator/parameter.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Automatische Speicherung", "autogenerator/autosave.html"));
			cat1.add(cat2);
		}

		// WorkEditor
		if(SHOW_WORKEDITOR) {
			cat1 = new DefaultMutableTreeNode(new HelpInfo("WorkEditor", "workeditor/main.html"));
			top.add(cat1);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Interaktion", "workeditor/interaction/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Fibonacci-Heap", "workeditor/interaction/fibheap.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Binomial-Queue", "workeditor/interaction/binqueue.html"));
			cat2.add(cat3);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Aufgabentypen", "workeditor/extypes/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Normal-Mode", "workeditor/extypes/normalmode.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Fault-Mode", "workeditor/extypes/faultmode.html"));
			cat2.add(cat3);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Task-Bereich", "workeditor/taskpanel.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Feedback-Bereich", "workeditor/feedbackpanel.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Anzeige durchgeführter Operationen", "workeditor/executedoperations.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Anfordern von Aufgaben", "workeditor/requestexercise.html"));
			cat1.add(cat2);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Aufgabe bearbeiten", "workeditor/workonexercise/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Normal-Mode", "workeditor/workonexercise/normalmode.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Fault-Mode", "workeditor/workonexercise/faultmode.html"));
			cat2.add(cat3);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Feedback-Typen", "workeditor/feedback/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Immediate Feedback & Error Correction", "workeditor/feedback/ifaec.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Error Flagging", "workeditor/feedback/errorflagging.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Demand-Feedback", "workeditor/feedback/demandfeedback.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("NoTutor", "workeditor/feedback/notutor.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Fault-Feedback", "workeditor/feedback/faultfeedback.html"));
			cat2.add(cat3);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Speichern/Laden von Aufgaben", "workeditor/loadsaveexercise.html"));
			cat1.add(cat2);
		}

		// EvalEditor
		if(SHOW_EVALEDITOR) {
			cat1 = new DefaultMutableTreeNode(new HelpInfo("EvalEditor", "evaleditor/main.html"));
			top.add(cat1);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Anzeige der durchgeführten Operationen", "evaleditor/executedoperations.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Operationskommentar", "evaleditor/operationcomment.html"));
			cat1.add(cat2);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("JEDAS-Annotationen", "evaleditor/jedasannotation/main.html"));
			cat1.add(cat2);

			cat3 = new DefaultMutableTreeNode(new HelpInfo("Notes-Fenster", "evaleditor/jedasannotation/noteswindow.html"));
			cat2.add(cat3);
			cat3 = new DefaultMutableTreeNode(new HelpInfo("Record-Fenster", "evaleditor/jedasannotation/recordwindow.html"));
			cat2.add(cat3);
	
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Aufgaben tutoriell evaluieren", "evaleditor/tutorevaluation.html"));
			cat1.add(cat2);
		}

		// EvalPlayer
		if(SHOW_EVALPLAYER) {
			cat1 = new DefaultMutableTreeNode(new HelpInfo("EvalPlayer", "evalplayer/main.html"));
			top.add(cat1);

			cat2 = new DefaultMutableTreeNode(new HelpInfo("Durchgeführte Operationen", "evalplayer/executedoperations.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Operationskommentar", "evalplayer/operationcomment.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Geschwindigkeits-Regler", "evalplayer/speedslider.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Zeit-Regler", "evalplayer/timeslider.html"));
			cat1.add(cat2);
			cat2 = new DefaultMutableTreeNode(new HelpInfo("Abspielen einer Aufgabe", "evalplayer/playexercise.html"));
			cat1.add(cat2);
		}
		return top;
	}
}
