/*
 * Copyright (c) 2006-2008 Maskat Project.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Maskat Project - initial API and implementation
 */
package org.maskat.ui.views.properties.tabbed.masterdetails;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;

import org.maskat.core.event.Event;
import org.maskat.ui.Messages;
import org.maskat.ui.views.properties.tabbed.beanwrapper.LocalCallbackFunctions;

public class LocalCallbackFunctionsDetailsPage extends
		AbstractMaskatDetailsPage {

	private static final String SECTION_TEXT = Messages
			.getString("localCallbackDetails.sectionText"); //$NON-NLS-1$

	private static final String DESCRIPTION = Messages
			.getString("localCallbackDetails.description"); //$NON-NLS-1$

	private FormToolkit toolkit;

	private Section callbackFunctionsSection;

	private Composite remoteComposite;

	private Composite localComposite;

	private Text beforeValidationLocalText;

	private Text afterStoredLocalText;

	private Text beforeValidationRemoteText;

	private Text beforeSendText;

	private Text afterReceiveText;

	private Text afterStoredRemoteText;

	private Text timeOutTimerText;

	private Text onTimeOutText;

	private Event event;

	private int lastOnTimerValue;
	
	public LocalCallbackFunctionsDetailsPage(TreeViewer masterBlockTreeViewer) {
		this.masterBlockTreeViewer = masterBlockTreeViewer;
	}

	public void createContents(Composite parent) {
		TableWrapLayout layout = new TableWrapLayout();
		layout.topMargin = 0;
		layout.leftMargin = 5;
		layout.rightMargin = 5;
		layout.bottomMargin = 5;
		parent.setLayout(layout);

		toolkit = managedForm.getToolkit();

		callbackFunctionsSection = toolkit.createSection(parent,
				ExpandableComposite.TITLE_BAR | Section.DESCRIPTION);
		callbackFunctionsSection.setText(SECTION_TEXT);
		callbackFunctionsSection.setDescription(DESCRIPTION);
		TableWrapData tableWrapData = new TableWrapData(TableWrapData.FILL,
				TableWrapData.TOP);
		tableWrapData.grabHorizontal = true;
		callbackFunctionsSection.setLayoutData(tableWrapData);

		createRemoteComposite();
		createLocalComposite();
	}

	public void refresh() {
		initializeInterface();
	}

	protected void initializeInterface() {
		if (event.getTimeout() >= 0) {
			lastOnTimerValue = event.getTimeout();
		}
		update();
	}

	public void selectionChanged(IFormPart part, ISelection selection) {
		update();
	}

	public void update() {
		if (event.getType().equals("remote")) {

			hideLocalComposite();
			showRemoteComposite();

			if (event.getStart() != null) {
				beforeValidationRemoteText.setText(event.getStart());
			} else {
				beforeValidationRemoteText.setText("");
			}

			if (event.getBefore() != null) {
				beforeSendText.setText(event.getBefore());
			} else {
				beforeSendText.setText("");
			}
			if (event.getAfter() != null) {
				afterReceiveText.setText(event.getAfter());
			} else {
				afterReceiveText.setText("");
			}

			if (event.getFinish() != null) {
				afterStoredRemoteText.setText(event.getFinish());
			} else {
				afterStoredRemoteText.setText("");
			}

			if (event.getTimeout() >= 0) {
				timeOutTimerText.setText(new Integer(event.getTimeout())
						.toString());

				if (event.getOnTimeoutError() != null) {
					onTimeOutText.setText(event.getOnTimeoutError());
				} else {
					onTimeOutText.setText("");
				}
				onTimeOutText.setEnabled(true);
			} else {
				timeOutTimerText.setText("");
				onTimeOutText.setText("");
				onTimeOutText.setEnabled(false);
			}

		} else if (event.getType().equals("local")) {
			hideRemoteComposite();
			showLocalComposite();

			if (event.getStart() != null) {
				beforeValidationLocalText.setText(event.getStart());
			} else {
				beforeValidationLocalText.setText("");
			}

			if (event.getFinish() != null) {
				afterStoredLocalText.setText(event.getFinish());
			} else {
				afterStoredLocalText.setText("");
			}
		}

		setDirtyFlag(false);
	}

	private void showLocalComposite() {
		callbackFunctionsSection.setClient(localComposite);
		localComposite.setVisible(true);
		callbackFunctionsSection.redraw();
		callbackFunctionsSection.update();

	}

	private void showRemoteComposite() {
		callbackFunctionsSection.setClient(remoteComposite);
		remoteComposite.setVisible(true);
		callbackFunctionsSection.redraw();
		callbackFunctionsSection.update();

	}

	private void hideRemoteComposite() {
		remoteComposite.setVisible(false);
		callbackFunctionsSection.redraw();
		callbackFunctionsSection.update();
	}

	private void hideLocalComposite() {
		localComposite.setVisible(false);
		callbackFunctionsSection.redraw();
		callbackFunctionsSection.update();
	}

	public Event getEvent() {
		return event;
	}

	public void setEvent(Event event) {
		this.event = event;
	}

	public void createRemoteComposite() {
		remoteComposite = toolkit.createComposite(callbackFunctionsSection);

		remoteComposite.setLayout(new GridLayout(3, false));

		toolkit.createLabel(remoteComposite, Messages
				.getString("localCallbackDetails.beforeValidationLabel")); //$NON-NLS-1$
		toolkit.createLabel(remoteComposite, ":");
		beforeValidationRemoteText = toolkit.createText(remoteComposite, event
				.getStart(), SWT.SINGLE | SWT.BORDER);
		beforeValidationRemoteText.setLayoutData(new GridData(SWT.FILL, 0,
				true, false));

		toolkit.createLabel(remoteComposite, Messages
				.getString("localCallbackDetails.beforeDataSentLabel")); //$NON-NLS-1$
		toolkit.createLabel(remoteComposite, ":");
		beforeSendText = toolkit.createText(remoteComposite, event.getBefore(),
				SWT.SINGLE | SWT.BORDER);
		beforeSendText.setLayoutData(new GridData(SWT.FILL, 0, true, false));

		toolkit.createLabel(remoteComposite, Messages
				.getString("localCallbackDetails.AfterDataReceiveLabel")); //$NON-NLS-1$
		toolkit.createLabel(remoteComposite, ":");
		afterReceiveText = toolkit.createText(remoteComposite,
				event.getAfter(), SWT.SINGLE | SWT.BORDER);
		afterReceiveText.setLayoutData(new GridData(SWT.FILL, 0, true, false));

		toolkit.createLabel(remoteComposite, Messages
				.getString("localCallbackDetails.AfterDataStoreLabel")); //$NON-NLS-1$
		toolkit.createLabel(remoteComposite, ":");
		afterStoredRemoteText = toolkit.createText(remoteComposite, event
				.getFinish(), SWT.SINGLE | SWT.BORDER);
		afterStoredRemoteText.setLayoutData(new GridData(SWT.FILL, 0, true,
				false));

		toolkit.createLabel(remoteComposite, Messages
				.getString("localCallbackDetails.TimerLabel")); //$NON-NLS-1$
		toolkit.createLabel(remoteComposite, ":");
		timeOutTimerText = toolkit.createText(remoteComposite, new Integer(
				event.getTimeout()).toString(), SWT.SINGLE | SWT.BORDER);
		timeOutTimerText.setSize(5, 0);
		timeOutTimerText.setLayoutData(new GridData(SWT.FILL, 0, false, false));

		toolkit.createLabel(remoteComposite, Messages
				.getString("localCallbackDetails.OnTimeoutLabel")); //$NON-NLS-1$
		toolkit.createLabel(remoteComposite, ":");
		onTimeOutText = new Text(remoteComposite, SWT.SINGLE | SWT.BORDER);
		onTimeOutText.setEnabled(false);
		onTimeOutText.setLayoutData(new GridData(SWT.FILL, 0, true, false));

		beforeValidationRemoteText.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				updateBeanBeforeValidation(beforeValidationRemoteText);
			}
		});

		beforeValidationRemoteText.addFocusListener(new FocusAdapter() {

			public void focusLost(FocusEvent e) {
				updateBeanBeforeValidation(beforeValidationRemoteText);
			}
		});

		beforeSendText.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				if (event.getBefore() == null
						|| !event.getBefore().equals(beforeSendText.getText())) {
					EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
							LocalCallbackFunctions.class, event, "before",
							beforeSendText.getText());
				}
			}
		});

		beforeSendText.addFocusListener(new FocusAdapter() {

			public void focusLost(FocusEvent e) {
				if (event.getBefore() == null
						|| !event.getBefore().equals(beforeSendText.getText())) {
					EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
							LocalCallbackFunctions.class, event, "before",
							beforeSendText.getText());
				}
			}
		});

		afterReceiveText.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				if (event.getAfter() == null
						|| !event.getAfter().equals(afterReceiveText.getText())) {
					EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
							LocalCallbackFunctions.class, event, "after",
							afterReceiveText.getText());
				}
			}
		});

		afterReceiveText.addFocusListener(new FocusAdapter() {

			public void focusLost(FocusEvent e) {
				if (event.getAfter() == null
						|| !event.getAfter().equals(afterReceiveText.getText())) {
					EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
							LocalCallbackFunctions.class, event, "after",
							afterReceiveText.getText());
				}
			}
		});

		afterStoredRemoteText.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				updateBeanAfterStored(afterStoredRemoteText);
			}
		});

		afterStoredRemoteText.addFocusListener(new FocusAdapter() {

			public void focusLost(FocusEvent e) {
				updateBeanAfterStored(afterStoredRemoteText);
			}
		});

		timeOutTimerText.addListener(SWT.Verify, new VerifyIntegerListener());

		timeOutTimerText.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				String timeOutTimerAsString = timeOutTimerText.getText();

				if (!timeOutTimerAsString.equals("")) {
					if (isTextValueValid(timeOutTimerText)) {
						onTimeOutText.setEnabled(true);
					} else {
						onTimeOutText.setEnabled(false);
					}
				} else {
					onTimeOutText.setEnabled(false);
				}

				if (event.getTimeout() != getTextValueAsIntValue(
						timeOutTimerText, lastOnTimerValue)) {
					EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
							LocalCallbackFunctions.class, event, "timeout",
							timeOutTimerText.getText());
				}
			}
		});

		timeOutTimerText.addFocusListener(new FocusListener() {

			public void focusGained(FocusEvent e) {
				lastOnTimerValue = event.getTimeout();
			}

			public void focusLost(FocusEvent e) {
				if (isTextValueValid(timeOutTimerText)) {
					if (event.getTimeout() != getTextValueAsIntValue(
							timeOutTimerText, lastOnTimerValue)) {
						EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
								LocalCallbackFunctions.class, event, "timeout",
								timeOutTimerText.getText());
					}
				} else if (!timeOutTimerText.getText().equals("")) {
					if (event.getTimeout() != lastOnTimerValue) {
						EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
								LocalCallbackFunctions.class, event, "timeout",
								new Integer(lastOnTimerValue).toString());
					}
					setDirtyFlag(true);
					update();
				}

				if (timeOutTimerText.getText().equals("")) {
					if (event.getTimeout() != -1) {
						EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
								LocalCallbackFunctions.class, event, "timeout",
								"-1");
					}
					if (event.getOnTimeoutError() != null) {
						EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
								LocalCallbackFunctions.class, event,
								"onTimeoutError", null);
					}

					onTimeOutText.setText("");
					onTimeOutText.setEnabled(false);
				}
			}
		});

		onTimeOutText.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				if (event.getOnTimeoutError() == null
						|| !event.getOnTimeoutError().equals(
								onTimeOutText.getText())) {
					EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
							LocalCallbackFunctions.class, event,
							"onTimeoutError", onTimeOutText.getText());
				}
			}
		});

		onTimeOutText.addFocusListener(new FocusAdapter() {

			public void focusLost(FocusEvent e) {
				if (event.getOnTimeoutError() == null
						|| !event.getOnTimeoutError().equals(
								onTimeOutText.getText())) {
					EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
							LocalCallbackFunctions.class, event,
							"onTimeoutError", onTimeOutText.getText());
				}
			}
		});

		callbackFunctionsSection.setClient(remoteComposite);
	}

	public void createLocalComposite() {
		localComposite = toolkit.createComposite(callbackFunctionsSection);

		localComposite.setLayout(new GridLayout(3, false));

		toolkit.createLabel(localComposite, Messages
				.getString("localCallbackDetails.beforeValidationLabel")); //$NON-NLS-1$
		toolkit.createLabel(localComposite, ":");
		beforeValidationLocalText = toolkit.createText(localComposite, event
				.getStart(), SWT.SINGLE | SWT.BORDER);
		beforeValidationLocalText.setLayoutData(new GridData(SWT.FILL, 0, true,
				false));

		toolkit.createLabel(localComposite, Messages
				.getString("localCallbackDetails.AfterDataStoreLabel")); //$NON-NLS-1$
		toolkit.createLabel(localComposite, ":");
		afterStoredLocalText = toolkit.createText(localComposite, event
				.getFinish(), SWT.SINGLE | SWT.BORDER);
		afterStoredLocalText.setLayoutData(new GridData(SWT.FILL, 0, true,
				false));

		beforeValidationLocalText.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent e) {
				updateBeanBeforeValidation(beforeValidationLocalText);
			}
		});
		beforeValidationLocalText.addFocusListener(new FocusAdapter() {

			public void focusLost(FocusEvent e) {
				updateBeanBeforeValidation(beforeValidationLocalText);
			}
		});

		afterStoredLocalText.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent e) {
				updateBeanAfterStored(afterStoredLocalText);
			}
		});
		afterStoredLocalText.addFocusListener(new FocusAdapter() {

			public void focusLost(FocusEvent e) {
				updateBeanAfterStored(afterStoredLocalText);
			}
		});
	}

	private void updateBeanBeforeValidation(Text textField) {
		if (event.getStart() == null
				|| !event.getStart().equals(textField.getText())) {
			EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
					LocalCallbackFunctions.class, event, "start", textField
							.getText());
		}
	}

	private void updateBeanAfterStored(Text textField) {
		if (event.getFinish() == null
				|| !event.getFinish().equals(textField.getText())) {
			EventPropertiesMasterDetailsBlock.setEventProperty(masterBlockTreeViewer,
					LocalCallbackFunctions.class, event, "finish", textField
							.getText());
		}
	}
}
