package semorg.gui;

import static org.eclipse.swt.SWT.BAR;
import static org.eclipse.swt.SWT.BORDER;
import static org.eclipse.swt.SWT.CASCADE;
import static org.eclipse.swt.SWT.DROP_DOWN;
import static org.eclipse.swt.SWT.PUSH;
import static org.eclipse.swt.SWT.SEPARATOR;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.sql.SQLException;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;

import java.util.Locale;
import java.util.Properties;

import semorg.conf.Configuration;
import semorg.gui.list.AssociateListWindow;
import semorg.gui.list.ClientBookingListWindow;
import semorg.gui.list.ClientListWindow;
import semorg.gui.list.CompanyBookingListWindow;
import semorg.gui.list.CompanyInternalPresentationListWindow;
import semorg.gui.list.CompanyListWindow;
import semorg.gui.list.LecturerListWindow;
import semorg.gui.list.PublicPresentationListWindow;
import semorg.gui.list.SeminarTypeListWindow;
import semorg.gui.util.AssociationTabControl;
import semorg.gui.util.Messages;
import semorg.sql.access.DBAccess;
import semorg.sql.util.Utility;

/**
 * The main window of the application providing several menus to gain access of
 * all the other windows of the application.
 */
public class MainWindow {

    /**
     * Static instance of the {@link MainWindow} to allow the other windows an
     * easy access to some call attributes (e.g. the {@link #shell}).
     */
    private static MainWindow instance;

    /** The shell (window) used to draw the {@link MainWindow}. */
    private Shell shell;

    /** The display which contains all the windows. */
    private Display display;

    /** Holds the configuration of the application. */
    private Configuration huSemOrgConf;

    /**
     * Creates a {@link MainWindow} instance with the given values.
     * 
     * @param disp
     *                The display used to draw the windows of this application.
     */
    public MainWindow(Display disp) {
	instance = this;

	this.huSemOrgConf = new Configuration();
	this.display = disp;
	this.shell = new Shell(display, SWT.CLOSE | SWT.TITLE | SWT.MIN);

	centerShell();

	shell.setText(Messages.getString("GUIText.MainWindowTitleText"));
	shell.setBackground(new Color(display, 33, 0, 144));
	shell.setBackgroundImage(Utility.getImage(huSemOrgConf
		.getProperty("background")));

	createMenu();

	// createStatusBar();
	createListWindows();

	shell.open();
	// the event loop
	while (!shell.isDisposed()) {
	    if (!shell.getDisplay().readAndDispatch()) {
		shell.getDisplay().sleep();
	    }
	}
	Utility.disposeImages();
	display.dispose();
    }

    /** Creates all static list window instances. */
    private void createListWindows() {
	AssociateListWindow.createWindow(shell);
	ClientBookingListWindow.createWindow(shell);
	ClientListWindow.createWindow(shell);
	CompanyBookingListWindow.createWindow(shell);
	CompanyInternalPresentationListWindow.createWindow(shell);
	CompanyListWindow.createWindow(shell);
	LecturerListWindow.createWindow(shell);
	PublicPresentationListWindow.createWindow(shell);
	SeminarTypeListWindow.createWindow(shell);
    }

    /** Centers the shell on the screen. */
    private void centerShell() {
	int Width = 792;
	int Height = 594;
	Rectangle pDisplayBounds = shell.getDisplay().getBounds();
	int nLeft = (pDisplayBounds.width - Width) / 2;
	int nTop = (pDisplayBounds.height - Height) / 2;
	shell.setBounds(nLeft, nTop, Width, Height);
    }

    /** Creates a status bar. */
    private void createStatusBar() {
	final ToolBar bar = new ToolBar(shell, BORDER);
	bar.setBounds(0, shell.getSize().y - 64, shell.getSize().x, 20);
    }

    /** Creats all the menus in the {@link MainWindow}. */
    private void createMenu() {
	Menu mainMenu = new Menu(shell, BAR);
	mainMenu.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "MainMenu");
	shell.setMenuBar(mainMenu);

	MenuItem mainMenuItem = new MenuItem(mainMenu, CASCADE);
	mainMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuApplicationText"));
	Menu subMenu = new Menu(shell, DROP_DOWN);
	mainMenuItem.setMenu(subMenu);
	MenuItem subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuApplicationImportText"));
	subMenuItem.setEnabled(false);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuApplicationExportText"));
	subMenuItem.setEnabled(false);
	subMenuItem = new MenuItem(subMenu, SEPARATOR);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem
		.setText(Messages
			.getString("GUIText.MainWindowMenuApplicationGenerateReportText"));
	subMenuItem.setEnabled(false);
	subMenuItem = new MenuItem(subMenu, SEPARATOR);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuApplicationExitText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		shell.close();
	    }
	});

	mainMenuItem = new MenuItem(mainMenu, CASCADE);
	mainMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuMasterDataListsText"));
	subMenu = new Menu(shell, DROP_DOWN);
	mainMenuItem.setMenu(subMenu);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemAssociateText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		AssociateListWindow.openList();
	    }
	});
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemLecturerText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		LecturerListWindow.openList();
	    }
	});

	subMenuItem = new MenuItem(subMenu, CASCADE);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemCompanyText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		CompanyListWindow.openList();
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemCompanyBookingText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		CompanyBookingListWindow.openList();
	    }
	});
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem
		.setText(Messages
			.getString("GUIText.MainWindowMenuItemCompanyInternalPresentationText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		CompanyInternalPresentationListWindow.openList();
	    }
	});
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemClientText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		ClientListWindow.openList();
	    }
	});
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemClientBookingText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		ClientBookingListWindow.openList();
	    }
	});
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemPublicPresentationText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		PublicPresentationListWindow.openList();
	    }
	});
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemSeminarTypeText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		SeminarTypeListWindow.openList();
	    }
	});

	mainMenuItem = new MenuItem(mainMenu, CASCADE);
	mainMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuInitialDataAcquisitionText"));
	subMenu = new Menu(shell, DROP_DOWN);
	mainMenuItem.setMenu(subMenu);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemAssociateText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new AssociateWindow(shell, null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemLecturerText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new LecturerWindow(shell, null, null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemCompanyText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new CompanyWindow(shell, null, null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemCompanyBookingText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new CompanyBookingWindow(shell, null, null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem
		.setText(Messages
			.getString("GUIText.MainWindowMenuItemCompanyInternalPresentationText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new CompanyInternalPresentationWindow(shell, null,
				(AssociationTabControl) null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemClientText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new ClientWindow(shell, null,
				(AssociationTabControl) null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemClientBookingText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new ClientBookingWindow(shell, null, null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemPublicPresentationText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new PublicPresentationWindow(shell, null,
				(AssociationTabControl) null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemSeminarTypeText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new SeminarTypeWindow(shell, null,
				(AssociationTabControl) null);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	mainMenuItem = new MenuItem(mainMenu, CASCADE);
	mainMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuUseCaseText"));
	subMenu = new Menu(shell, DROP_DOWN);
	mainMenuItem.setMenu(subMenu);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemBookSeminarText"));
	subMenuItem.setEnabled(false);

	mainMenuItem = new MenuItem(mainMenu, CASCADE);
	mainMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuAdministrationText"));
	subMenu = new Menu(shell, DROP_DOWN);
	mainMenuItem.setMenu(subMenu);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemManageEnumerationsText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new EnumerationWindow(shell);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemSelectLanguageText"));
	subMenuItem.setEnabled(true);
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			new SelectLanguageWindow(shell);
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

	//TODO: do the null test in Configuration class 
	if ((huSemOrgConf.getProperty("selectLanguage") != null)
		&& (huSemOrgConf.getProperty("selectLanguage"))
			.equals("disabled")) {
	    subMenuItem.setEnabled(false);
	}

	mainMenuItem = new MenuItem(mainMenu, CASCADE);
	mainMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuHelpText"));
	subMenu = new Menu(shell, DROP_DOWN);
	mainMenuItem.setMenu(subMenu);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemContentsText"));
	subMenuItem.setEnabled(false);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemContextHelpText"));
	subMenuItem.setEnabled(false);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemAboutHelpText"));
	subMenuItem.setEnabled(false);
	subMenuItem = new MenuItem(subMenu, SEPARATOR);
	subMenuItem = new MenuItem(subMenu, PUSH);
	subMenuItem.setText(Messages
		.getString("GUIText.MainWindowMenuItemInfoText"));
	subMenuItem.addSelectionListener(new SelectionAdapter() {

	    public void widgetSelected(SelectionEvent event) {
		Runnable newShellOpener = new Runnable() {
		    public void run() {
			MessageDialog
				.openInformation(
					null,
					Messages
						.getString("GUIText.MainWindowApplicationInformationTitleText"),
					Messages
						.getString("GUIText.MainWindowApplicationInformationText"));
		    }
		};
		shell.getDisplay().syncExec(newShellOpener);
	    }
	});

    }

    public Shell getShell() {
	return shell;
    }

    /** Returns the static instance of the {@link MainWindow}. */
    public static MainWindow getInstance() {
	return instance;
    }

    /**
     * Returns a {@link Configuration} object which contains the actual
     * configuration.
     */
    public Configuration getConfiguration() {
	return huSemOrgConf;
    }

    /**
     * Saves the actual configuration to the configuration file.
     */

    /**
     * The main function which implements the application starting process:
     * <ul>
     * <li>loading the configuration file or create one with the default
     * configuration if it does not exist.</li>
     * <li>initialization of the database connection including the creating of
     * the catalog and its tables if they does not exist.</li>
     * <li>creating a {@link MainWindow} instance. </li>
     * </ul>
     */
    public static void main(String[] args) {
	// make config
	try {
	    DBAccess.init();
	    Utility.initUtilities();
	} catch (ClassNotFoundException e) {
	    System.out
		    .println("The MySQL database driver was not found in the classpath.");
	    System.exit(1);
	} catch (SQLException e) {
	    e.printStackTrace();
	    System.exit(2);
	}

	new MainWindow(Display.getDefault());
    }
}
