package semorg.gui.list;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Shell;

import semorg.gui.CompanyInternalPresentationWindow;
import semorg.gui.CompanyWindow;
import semorg.gui.MainWindow;
import semorg.gui.provider.CompanyTableProvider;
import semorg.gui.util.AssociationTabControl;
import semorg.gui.util.DBTableChangedListener;
import semorg.gui.util.ForeignKeyConstraintSelector;
import semorg.gui.util.Messages;
import semorg.sql.tables.Company;
import semorg.sql.tables.SimpleIDKey;
import semorg.sql.util.DBConstraint;
import semorg.sql.util.DistinctVector;
import semorg.sql.util.Utility;

/**
 * Provides the list window for company data records. This
 * class can be instantiated as normal list windows using the menu the
 * {@link MainWindow} as well as popup list windows by the controls
 * {@link AssociationTabControl} and {@link ForeignKeyConstraintSelector}.
 */
public class CompanyListWindow extends ListWindow {

    /**
     * A static instance of the actual list window. It is used to update the
     * input of the list window when a object gets changes in the
     * {@link CompanyWindow}.
     */
    public static ListWindow instance;

    /** Instantiates a new list window. */
    public CompanyListWindow() {
	super(MainWindow.getInstance().getShell(), Company.getColumns());

	mainTableViewer.setLabelProvider(new CompanyTableProvider());

	shell.setText(Messages.getString("GUIText.CompanyListWindowTitleText"));

	update();
    }

    /**
     * Instantiates a new list window as a popup.
     * 
     * @param caller
     *                the {@link ForeignKeyConstraintSelector} instance which
     *                wants to create this list window
     */
    public CompanyListWindow(AssociationTabControl caller) {
	super(caller.getShell(), Company.getColumns(), caller);

	mainTableViewer.setLabelProvider(new CompanyTableProvider());

	shell.setText(Messages
		.getString("GUIText.PopUpCompanyListWindowTitleText"));

	update();
	shell.open();
    }

    /**
     * Instantiates a new list window as a popup.
     * 
     * @param caller
     *                the {@link AssociationTabControl} instance which wants to
     *                create this list window
     */
    public CompanyListWindow(ForeignKeyConstraintSelector caller) {
	super(caller.getShell(), Company.getColumns(), caller);

	mainTableViewer.setLabelProvider(new CompanyTableProvider());

	shell.setText(Messages
		.getString("GUIText.PopUpCompanyListWindowTitleText"));

	update();
	shell.open();
    }

    /**
     * Adds a listener to the mainTableViewer which opens a edit dialog to edit
     * the doubleclicked item.
     * 
     * @see semorg.gui.list.ListWindow#createSpecializedMainTableListener()
     */
    protected void createSpecializedMainTableListener() {
	addUpdateListener(DBTableChangedListener.TYPE_COMPANY);

	mainTableViewer.addDoubleClickListener(new IDoubleClickListener() {

	    public void doubleClick(DoubleClickEvent event) {
		StructuredSelection selection = (StructuredSelection) event
			.getSelection();
		Company selectedItem = (Company) selection.getFirstElement();
		new CompanyWindow(MainWindow.getInstance().getShell(),
			selectedItem, null);
	    }
	});
    }

    /**
     * Adds a listener to the mainTableViewer which inserts the doubleclicked
     * item into the calling {@link AssociationTabControl} instance.
     * 
     * @see semorg.gui.list.ListWindow#createSpecializedMainTableListener(semorg.gui.util.AssociationTabControl)
     */
    protected void createSpecializedMainTableListener(
	    final AssociationTabControl caller) {
	addUpdateListener(DBTableChangedListener.TYPE_COMPANY);

	mainTableViewer.addDoubleClickListener(new IDoubleClickListener() {

	    public void doubleClick(DoubleClickEvent event) {
		StructuredSelection selection = (StructuredSelection) event
			.getSelection();
		Company selectedItem = (Company) selection.getFirstElement();

		caller.addSelectedIds(new SimpleIDKey[] { selectedItem }, true);
		shell.close();
	    }
	});
    }

    /**
     * Adds a listener to the mainTableViewer which inserts the doubleclicked
     * item into the calling {@link ForeignKeyConstraintSelector} instance. *
     * 
     * @see semorg.gui.list.ListWindow#createSpecializedMainTableListener(semorg.gui.util.ForeignKeyConstraintSelector)
     */
    protected void createSpecializedMainTableListener(
	    final ForeignKeyConstraintSelector caller) {
	addUpdateListener(DBTableChangedListener.TYPE_COMPANY);

	mainTableViewer.addDoubleClickListener(new IDoubleClickListener() {

	    public void doubleClick(DoubleClickEvent event) {
		StructuredSelection selection = (StructuredSelection) event
			.getSelection();
		Company selectedItem = (Company) selection.getFirstElement();
		caller.setSelectedId(selectedItem.getId());
		shell.close();
	    }
	});
    }

    /** @see semorg.gui.list.ListWindow#createSpecializedToolBarListeners() */
    protected void createSpecializedToolBarListeners() {
	editItem.addSelectionListener(new SelectionListener() {

	    public void widgetSelected(SelectionEvent event) {
		IStructuredSelection selection = (IStructuredSelection) mainTableViewer
			.getSelection();
		Company selectedElement = (Company) selection.getFirstElement();
		new CompanyWindow(MainWindow.getInstance().getShell(),
			selectedElement, null);
	    }

	    public void widgetDefaultSelected(SelectionEvent arg0) {
		widgetSelected(arg0);
	    }
	});

	deleteItem.addSelectionListener(new SelectionListener() {

	    public void widgetSelected(SelectionEvent event) {
		IStructuredSelection selection = (IStructuredSelection) mainTableViewer
			.getSelection();
		DistinctVector<Company> selectedElements = new DistinctVector(
			(List<Company>) selection.toList());

		String question = (selectedElements.size() > 1) ? Messages
			.getString("GUIText.DeleteCompanyItemsMessageDialogText")
			: Messages
				.getString("GUIText.DeleteCompanyItemMessageDialogText");
		MessageDialog dlg = new MessageDialog(
			MainWindow.getInstance().getShell(),
			Messages
				.getString("GUIText.DeleteItemMessageDialogTitle"),
			null,
			question,
			MessageDialog.QUESTION,
			new String[] {
				Messages
					.getString("GUIText.DeleteItemMessageDialogYesButtonText"),
				Messages
					.getString("GUIText.DeleteItemMessageDialogNoButtonText") },
			0);

		if (dlg.open() != 0) {// not "yes" selected
		    return;
		}

		try {
		    Iterator<Company> it = selectedElements.iterator();
		    while (it.hasNext()) {
			int id = it.next().getId();
			if (Company.lockedIds.contains(new Integer(id))) {
			    MessageDialog
				    .openInformation(
					    shell,
					    Messages
						    .getString("GUIText.DeleteErrorDialogTitle"),
					    Messages
						    .getString("GUIText.DeleteErrorDialogText"));
			    return;
			}
		    }
		    Company.removeFromDB(selectedElements);
		    CompanyListWindow.instance.update();
		} catch (SQLException e) {
		    e.printStackTrace();
		}
	    }

	    public void widgetDefaultSelected(SelectionEvent arg0) {
		widgetSelected(arg0);
	    }
	});

	newItem.addSelectionListener(new SelectionListener() {

	    public void widgetSelected(SelectionEvent event) {
		new CompanyWindow(MainWindow.getInstance().getShell(), null,
			null);
	    }

	    public void widgetDefaultSelected(SelectionEvent event) {
		widgetSelected(event);
	    }
	});
    }

    /** @see semorg.gui.list.ListWindow#createChooseButtonListener(semorg.gui.util.AssociationTabControl) */
    protected void createChooseButtonListener(final AssociationTabControl caller) {
	chooseButton.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		StructuredSelection selection = (StructuredSelection) mainTableViewer
			.getSelection();
		if (!selection.isEmpty()) {

		    Object[] selectedItems = selection.toArray();
		    SimpleIDKey[] selectedElements = (SimpleIDKey[]) Utility
			    .castArray(selectedItems, SimpleIDKey.class);

		    caller.addSelectedIds(selectedElements, true);
		    shell.close();
		}
	    }
	});
    }

    /**
     * Adds a listener to the mainTableViewer which inserts the doubleclicked
     * item into the calling {@link ForeignKeyConstraintSelector} instance.
     * 
     * @see semorg.gui.list.ListWindow#createSpecializedMainTableListener(semorg.gui.util.ForeignKeyConstraintSelector)
     */
    protected void createChooseButtonListener(
	    final ForeignKeyConstraintSelector caller) {
	chooseButton.addSelectionListener(new SelectionAdapter() {
	    public void widgetSelected(SelectionEvent e) {
		StructuredSelection selection = (StructuredSelection) mainTableViewer
			.getSelection();
		if (!selection.isEmpty()) {
		    Company selectedItem = (Company) selection
			    .getFirstElement();
		    caller.setSelectedId(selectedItem.getId());
		    shell.close();
		}
	    }
	});
    }

    /** Opens the shell of the static list window instance. */
    public static void openList() {
	instance.shell.open();
    }

    /** @see semorg.gui.list.ListWindow#getTableInputFromDB() */
    protected Object getTableInputFromDB() {
	Vector<DBConstraint> constraints = null;

	// if active, read filter
	if (filterItem.getSelection()) {
	    try {
		constraints = filter.getConstraints();
	    } catch (Exception e) {
		// invalid filter value => switch off the filter
		filterItem.setSelection(false);
	    }
	}

	try {
	    return Company.getVectorFromDB(constraints, sortString);
	} catch (SQLException e) {
	    e.printStackTrace();
	}
	return new DistinctVector<Company>();
    }

    /**
     * Creates the static list window instance.
     * 
     * @param parent
     *                the parent shell.
     */
    public static void createWindow(Shell parent) {
	instance = new CompanyListWindow();
    }

}
