
import com.tildemh.jgwizard.*;
import org.gnu.gtk.*;
import java.util.*;
import java.io.IOException;

/**
 * A graphical interface for the domesday application. This program aids in the
 * construction of project settings files and then interacts with the main
 * domesday classes to generate the indices.
 *
 * <p>The gui is a Gtk+ application, created with the aid of the <a
 * href="http://java-gnome.sf.net">Java-Gnome</a> framework. 
 *
 * <p>The special wizard interface used (including the navigation tree) is
 * handled by the jgwizard class, which has been developed alongside the
 * domesday project.
 */
public class DomesdayGUI extends WizardForm{

	/**
	 * The domesday project settings. This object will load the settings, save
	 * the settings and store the settings during the editing process.
	 */
	protected static Project project = null;
	
	/** 
	 * Bundle used for all the GUI localization resources.
	 */
	protected static ResourceBundle messages;

	/** 
	 * Log object used throughout the generation of the indices
	 */
	protected static IGLog log;

	/** 
	 * Bridge between gui and text mode application classes
	 */
	private static Bridge bridge;
	
	/**
	 * The main gui application.
	 */
	public DomesdayGUI(){
		super("Domesday GUI "+IGLog.INDEXGEN_VERSION);
		
	}	

	/**
	 * Creates the application.
	 */
	public static void main( String[] args){
		Gtk.init(args);
		DomesdayGUI gui = new DomesdayGUI();
		Gtk.main();
		//TODO close log at some point!!		log.close();
	}

	
	/*
	 * The following are important pages of the wizard. Each is documented in
	 * it's own class. They appear here as global variables as they are required
	 * later by the classes to adjust the tree 
	 */
	private static WizardPage projectPage = null;
	private static WizardPage indexSource = null;
	private static WizardPage fileSysSource = null;
	private static WizardPage httpHeaders = null;
	private static WizardPage dirRoot = null;
	private static WizardPage fileRoot = null;
	private static WizardPage urlRoot = null;
	private static WizardPage scanIncFilters = null;
	private static WizardPage scanExcFilters = null;
	private static WizardPage indexIncFilters = null;
	private static WizardPage indexExcFilters = null;
	private static WizardPage selectType = null;
	private static WizardPage selectTemplate = null;

	private static WizardPage sitemapStart = null;
	private static WizardPage orderedListStart = null;
	private static WizardPage startProcessing = null;
	private static WizardPage progress = null;
	private static WizardPage summary = null;
	
	/**
	 * Customisations to the interface. This is a crucial abstract method of the
	 * WizardForm class, used for setting up the application
	 */
	public void customise(){	
	    messages = ResourceBundle.getBundle("GUIStrings",Locale.getDefault());

		bridge = new Bridge(messages, getWindow());
		// todo: handle io exception from this.
		try{
	    	ResourceBundle domesdayMessages = ResourceBundle.getBundle("MainStrings", Locale.getDefault());
			log = new IGLog(Domesday.getLogFileName(), domesdayMessages, bridge);
		}catch(IOException e){
			System.err.print("DomesDay IO Exception: "+e);
		}
		// Display an image in the top left corner
		VBox topLeft = new VBox(false, 10);
		super.setTopLeft( topLeft );
		//todo: this is temporary:
//		addHint(topLeft, new Hint("This is the top left vbox"));

		Image logo = new Image("img/domesday.png");
		topLeft.add(logo);
		Label version = new Label("Version "+IGLog.INDEXGEN_VERSION);
		version.setJustification(Justification.CENTER);
		topLeft.add(version);				
		
		/** Introductory screen */
		WizardPage welcome = new WelcomePage((WizardForm) this, null);
		welcome.setButtonVisibility(false, true);
		this.setFirstPage(welcome);
		welcome.setVisibility( WizardPageVisibility.VISIBLE );
		
		/** project load / save / close. Includes recent file list */
		projectPage = new ProjectPage((WizardForm) this, welcome);
		welcome.setFirstChild(projectPage);

		// The following pages are not connected to the tree until the project
		// is loaded

		/** Select indexing type - server or filesystem */
		indexSource = new IndexSourcePage((WizardForm) this, welcome);
		
		/** If filesys method, either dirscan or linkfollow type. */
		fileSysSource = new FileSysMethodPage((WizardForm) this, indexSource);
		indexSource.setFirstChild( fileSysSource );

		/** Directories to scan */
		dirRoot = new RootPage((WizardForm) this, indexSource, "DirRoot", "SCAN_ROOT");
		fileSysSource.joinNextScreen(dirRoot);

		/** Directories to scan */
		fileRoot = new RootPage((WizardForm) this, indexSource, "FileRoot", "SCAN_ROOT");
		
		/** URLs to scan */
		urlRoot = new RootPage((WizardForm) this, indexSource, "URLRoot", "SCAN_ROOT");

		/** HTTP Headers to send */
		httpHeaders = new SimpleTextPage((WizardForm) this, indexSource, messages.getString("HTTPHeaderTitle"), "HTTPHeaderHead", "HTTP_HEADERS");
		urlRoot.joinNextScreen(httpHeaders);
		
		/** scanIncFilters */
		scanIncFilters = new RootPage((WizardForm) this, indexSource, "ScanIncFilters", "SCAN_INCLUDE_FILTERS");
		
		/** scanExcFilters */
		scanExcFilters = new RootPage((WizardForm) this, indexSource, "ScanExcFilters", "SCAN_EXCLUDE_FILTERS");
		scanIncFilters.joinNextScreen(scanExcFilters);
		
		/** indexIncFilters */
		indexIncFilters = new RootPage((WizardForm) this, indexSource, "IndexIncFilters", "INDEX_INCLUDE_FILTERS");
		scanExcFilters.joinNextScreen(indexIncFilters);
		
		/** indexExcFilters */
		indexExcFilters = new RootPage((WizardForm) this, indexSource, "IndexExcFilters", "INDEX_EXCLUDE_FILTERS");
		indexIncFilters.joinNextScreen(indexExcFilters);
		
		/** Decides which type of index to create. */
		selectType = new IndexTypePage((WizardForm) this, welcome);
		indexSource.joinNextScreen(selectType);

		/** allows user to load a template file */
		selectTemplate = new TemplatePage((WizardForm) this, welcome);
		selectType.joinNextScreen(selectTemplate);

		/** Parent for the sitemap settings screens */
		sitemapStart = new SMStartPage((WizardForm) this, welcome);
		sitemapStart.setVisibility(WizardPageVisibility.VISIBLE);
		selectTemplate.joinNextScreen(sitemapStart);			

		/** Sitemap StartText */
		WizardPage smStartText = new SimpleTextPage((WizardForm) this, sitemapStart, messages.getString("SMStartTxtTitle"), "SMStartTxt", "SM_START_TXT");
		sitemapStart.setFirstChild(smStartText);

		/** Sitemap hierarchy page */
		WizardPage smHierarchy = new SMHierarchyPage((WizardForm) this, sitemapStart);
		smStartText.joinNextScreen(smHierarchy);

		/** Sitemap Links */
		WizardPage smLinks = new SimpleTextPage((WizardForm) this, sitemapStart, messages.getString("SMLinksTitle"), "SMLinksHead", "SM_LINKS_TXT");
		smHierarchy.joinNextScreen(smLinks);

		/** SiteMap End Text */
		WizardPage smEndText = new SimpleTextPage((WizardForm) this, sitemapStart, messages.getString("SMEndTextTitle"), "SMEndTextHead", "SM_END_TXT");
		smLinks.joinNextScreen(smEndText);

		/** OrderedList start page. Includes selecting sort key and articles. */
		orderedListStart = new OLStartPage((WizardForm) this, welcome);

		/** Orderd List start text */
		WizardPage olStartTxt = new SimpleTextPage((WizardForm) this, orderedListStart, messages.getString("OLStartTxtTitle"), "OLStartTxtHead", "OL_START_TXT");
		orderedListStart.setFirstChild(olStartTxt);

		/** OL navigation table */
		WizardPage olNavigation = new NYIPage((WizardForm) this, orderedListStart, "ol navigation");
		olStartTxt.joinNextScreen(olNavigation);

		/** OL Sections */
		WizardPage olSections = new OLSectionPage((WizardForm) this, orderedListStart);
		olNavigation.joinNextScreen(olSections);

		/** OL Link text */
		WizardPage olLinkTxt = new SimpleTextPage((WizardForm) this, orderedListStart, messages.getString("OLLinksTitle"), "OLLinksHead", "OL_LINK");
		olSections.joinNextScreen(olLinkTxt);

		/** OL End Txt */
		WizardPage olEndTxt = new SimpleTextPage((WizardForm) this, orderedListStart, messages.getString("OLEndTextTitle"), "OLEndTextHead", "OL_END_TXT");
		olLinkTxt.joinNextScreen(olEndTxt);
		
		/** Output location / begin */
		startProcessing = new StartProcessingPage((WizardForm) this, welcome);
		sitemapStart.joinNextScreen(startProcessing);

		/** Progress */
		progress = new ProgressPage((WizardForm) this, startProcessing, bridge);
		startProcessing.setFirstChild(progress);

		/** job done / complete page */
		summary = new SummaryPage((WizardForm) this, startProcessing, bridge);
		
		/** Bugs page */
		WizardPage bugs = new BugPage((WizardForm) this, null);
		welcome.joinNextScreen(bugs);
		bugs.setVisibility(WizardPageVisibility.VISIBLE);
		
		/** about page */
		WizardPage about = new AboutPage((WizardForm) this, null);
		bugs.joinNextScreen(about);
		about.setVisibility(WizardPageVisibility.VISIBLE);
		about.setButtonVisibility(true, false);		


		addHint(getTree(), new Hint( messages.getString("TreeHint") ) );
	}

	/**
	 * This is called when the project is changed (new/load/close). It sets up
	 * the wizard structure
	 */
	protected void changeProject(){
		if (project == null){
			projectPage.setNextScreen(null);
			indexSource.setVisibility(WizardPageVisibility.HIDDEN);
			sitemapStart.setVisibility(WizardPageVisibility.HIDDEN);
			orderedListStart.setVisibility(WizardPageVisibility.HIDDEN);
			selectTemplate.setVisibility(WizardPageVisibility.HIDDEN);
			selectType.setVisibility(WizardPageVisibility.HIDDEN);
			startProcessing.setVisibility(WizardPageVisibility.HIDDEN);
			indexIncFilters.setVisibility(WizardPageVisibility.HIDDEN);
			indexExcFilters.setVisibility(WizardPageVisibility.HIDDEN);
			scanIncFilters.setVisibility(WizardPageVisibility.HIDDEN);
			scanExcFilters.setVisibility(WizardPageVisibility.HIDDEN);
			fixVisibility(indexSource);
			fixVisibility(sitemapStart);
			fixVisibility(orderedListStart);
			fixVisibility(selectType);
			fixVisibility(selectTemplate);
			fixVisibility(startProcessing);
			
		}else{
			projectPage.joinNextScreen(indexSource);
			indexSource.setVisibility(WizardPageVisibility.VISIBLE);
			fixVisibility(indexSource);
			changeIndexSource();
			selectType.setVisibility(WizardPageVisibility.VISIBLE);
			fixVisibility(selectType);
			changeIndexType();
			changeFileSysMethod();
		}
	}

	/**
	 * When the index type is changed, this will change the settings pages which
	 * are being displayed
	 */
	protected void changeIndexType(){
		System.out.println("Change index Type");
		try{
			if (project.getEnumSetting("INDEX_TYPE").equals("INDEX_TYPE_SITE_MAP")){
				sitemapStart.setVisibility(WizardPageVisibility.VISIBLE);
				selectTemplate.joinNextScreen(sitemapStart);			
				orderedListStart.setVisibility(WizardPageVisibility.HIDDEN);
				sitemapStart.joinNextScreen(startProcessing);
				orderedListStart.setNextScreen(null);
			}else{
				orderedListStart.setVisibility(WizardPageVisibility.VISIBLE);
				selectTemplate.joinNextScreen(orderedListStart);			
				sitemapStart.setVisibility(WizardPageVisibility.HIDDEN);
				sitemapStart.setNextScreen(null);
				orderedListStart.joinNextScreen(startProcessing);
			}
			fixVisibility(sitemapStart);
			fixVisibility(orderedListStart);
		}catch(IllegalVariableException e){
			log.addError(203, "ILLEGAL_VAR_EXCEPTION", new Object[] { e.toString() } );
			e.printStackTrace();
		}
	}

	/**
	 * Following a change to the index source, this will set up which child
	 * screens are to be used.
	 */
	protected void changeIndexSource(){
		System.out.println("Change index source");
		boolean useServer = false;
		try{
			useServer = project.getEnumSetting("GET_METHOD").equals(
				"GET_METHOD_SERVER");
		}catch(IllegalVariableException e){
			log.addError(203, "ILLEGAL_VAR_EXCEPTION", new Object[] { e.toString() } );
			e.printStackTrace();
		}
		if (useServer){
			// want to use server.
			indexSource.setFirstChild( urlRoot );
			urlRoot.setVisibility( WizardPageVisibility.VISIBLE);
			httpHeaders.setVisibility( WizardPageVisibility.VISIBLE);
			fileSysSource.setVisibility(WizardPageVisibility.HIDDEN);
			dirRoot.setVisibility(WizardPageVisibility.HIDDEN);
			fileRoot.setVisibility(WizardPageVisibility.HIDDEN);
			urlRoot.joinNextScreen(scanIncFilters);
			fixVisibility( urlRoot );
			fixVisibility( fileSysSource );
		}else{
			// disk work.
			indexSource.setFirstChild( fileSysSource );
			urlRoot.setVisibility( WizardPageVisibility.HIDDEN);
			httpHeaders.setVisibility( WizardPageVisibility.HIDDEN);
			fixVisibility( urlRoot );
			changeFileSysMethod();
		}
	}

	/**
	 * Called following a change to the filsystem scan method
	 */
	protected void changeFileSysMethod(){
		System.out.println("changeFileSysMethod()");
		try{
			if (project.getEnumSetting("GET_METHOD").equals(
					"GET_METHOD_SERVER")){
				fileSysSource.setVisibility(WizardPageVisibility.HIDDEN);
				fixVisibility( fileSysSource );
				return;
			}
		}catch(IllegalVariableException e){
			log.addError(203, "ILLEGAL_VAR_EXCEPTION", new Object[] { e.toString() } );
			e.printStackTrace();
		}


		fileSysSource.setVisibility(WizardPageVisibility.VISIBLE);
		fixVisibility( fileSysSource );

		boolean useDirScan = true;
		try{
			useDirScan = project.getEnumSetting("FILE_SYSTEM_SEARCH").equals(
				"FILE_SYSTEM_SEARCH_DIR_SCAN");
		}catch(IllegalVariableException e){
			log.addError(203, "ILLEGAL_VAR_EXCEPTION", new Object[] { e.toString() } );
			e.printStackTrace();
		}
		if (useDirScan){
			// want to use dirScan.
			fileSysSource.joinNextScreen(dirRoot);
			dirRoot.setVisibility( WizardPageVisibility.VISIBLE);
			fileRoot.setVisibility(WizardPageVisibility.HIDDEN);
			dirRoot.joinNextScreen(scanIncFilters);
			fixVisibility( fileRoot );
			fixVisibility( dirRoot );
		}else{
			// linkfollow
			fileSysSource.joinNextScreen(fileRoot);
			fileRoot.setVisibility( WizardPageVisibility.VISIBLE);
			dirRoot.setVisibility(WizardPageVisibility.HIDDEN);
			fileRoot.joinNextScreen(scanIncFilters);
			fixVisibility( dirRoot );
			fixVisibility( fileRoot );
		}
	}

	/** 
	 * Attach summary &amp; log pages 
	 */
	protected void generated(){
		progress.joinNextScreen(summary);
	}
}
