//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 IBM Corporation and others.
// 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.publishing.ui.preferences;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.epf.authoring.ui.AuthoringUIText;
import org.eclipse.epf.authoring.ui.preferences.CommonPrefPage;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.layout.DefaultContentValidator;
import org.eclipse.epf.publishing.PublishingPlugin;
import org.eclipse.epf.publishing.ui.PublishingUIResources;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

/**
 * The Publishing preference page.
 * 
 * @author Kelvin Low
 * @since 1.0
 * 
 * Bugs fixed:
 * <ul>
 * <li>https://bugs.eclipse.org/bugs/show_bug.cgi?id=156957</li>
 * </ul>
 */
public class PublishingPreferencePage extends CommonPrefPage implements
		IWorkbenchPreferencePage, SelectionListener, ModifyListener {

	private Composite composite;

	private Text destinationPathText;

	private Text feedbackURLText;

	private Button browseButton;

	private Button extraDescriptorInfoCtr;

	public static final String EXTRA_DESCRIPTOR_INFO = "org.eclipse.epf.publishing.ui.preferences.extraDescriptorInfo"; //$NON-NLS-1$		

	protected Control createContents(Composite parent) {
		composite = new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout(1, false));

		// Create the Destination Path group.
		Group destinationGroup = new Group(composite, SWT.NULL);
		destinationGroup.setLayout(new GridLayout(3, false));
		destinationGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		destinationGroup
				.setText(PublishingUIResources.destinationDirectoryGroup_text);

		createLabel(destinationGroup,
				PublishingUIResources.preferencePage_defaultPath_text);
		destinationPathText = createEditableText(destinationGroup, ""); //$NON-NLS-1$
		destinationPathText.setText(PublishingUIPreferences.getPublishPath());
		browseButton = new Button(destinationGroup, SWT.NONE);
		browseButton.setText(AuthoringUIText.BROWSE_BUTTON_TEXT);

		// Create the Published Website group.
		Group webSiteGroup = new Group(composite, SWT.NULL);
		webSiteGroup.setLayout(new GridLayout(2, false));
		webSiteGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		webSiteGroup.setText(PublishingUIResources.publishWebSiteGroup_text);

		createLabel(webSiteGroup, PublishingUIResources.feedbackURLLabel_text);
		feedbackURLText = createEditableText(webSiteGroup, ""); //$NON-NLS-1$
		feedbackURLText.setText(PublishingUIPreferences.getFeedbackURL());
		createLabel(webSiteGroup, ""); //$NON-NLS-1$

		// Create the layout group.
		Group layoutGroup = new Group(composite, SWT.NULL);
		layoutGroup.setLayout(new GridLayout(2, false));
		layoutGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		layoutGroup.setText(PublishingUIResources.layoutGroup_text);

		extraDescriptorInfoCtr = new Button(layoutGroup, SWT.CHECK);
		extraDescriptorInfoCtr
				.setText(PublishingUIResources.publishExtraDescriptorInfoLabel_text);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 2;
		extraDescriptorInfoCtr.setLayoutData(gd);
		extraDescriptorInfoCtr.setSelection(PublishingUIPreferences
				.getExtraDescriptorInfo());

		initializeValues();

		destinationPathText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				if (!isPathValid(destinationPathText.getText())) {
					setValid(false);
				} else {
					setValid(true);
				}
			}
		});
		browseButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				openDirectoryDialog();
			}
		});

		return composite;
	}

	public void init(IWorkbench workbench) {
	}

	public void widgetSelected(SelectionEvent e) {
	}

	public void widgetDefaultSelected(SelectionEvent e) {
	}

	public void modifyText(ModifyEvent e) {
	}

	/**
	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults
	 */
	protected void performDefaults() {
		super.performDefaults();
		initializeDefaults();
	}

	/**
	 * Method declared on PreferencePage
	 */
	public boolean performOk() {
		storeValues();
		PublishingUIPreferences.saveAllPreferences();
		return true;
	}

	/**
	 * Stores the values of the controls back to the preference store.
	 */
	private void storeValues() {
		PublishingUIPreferences.setPublishPath(destinationPathText.getText()
				.trim());
		PublishingUIPreferences
				.setFeedbackURL(feedbackURLText.getText().trim());
		PublishingUIPreferences.setExtraDescriptorInfo(extraDescriptorInfoCtr
				.getSelection());

		// FIXME! Review implementation.
		// allow to pass the value to the library browsing
		// System.setProperty(EXTRA_DESCRIPTOR_INFO,
		// extraDescriptorInfoCtr.getSelection() ? "true" : "false");
		DefaultContentValidator
				.setDefaultShowExtraInfoForDescriptors(extraDescriptorInfoCtr
						.getSelection());

	}

	private void initializeDefaults() {
		destinationPathText.setText(PublishingUIPreferences
				.getDefaultPublishPath());
		feedbackURLText
				.setText(PublishingUIPreferences.getDefaultFeedbackURL());
		extraDescriptorInfoCtr.setSelection(PublishingUIPreferences
				.getDefaultExtraDescriptorInfo());
	}

	/**
	 * Initializes states of the controls from the preference store.
	 */
	private void initializeValues() {
	}

	protected IPreferenceStore doGetPreferenceStore() {
		return PublishingPlugin.getDefault().getPreferenceStore();
	}

	protected Label createLabel(Composite parent, String text) {
		Label label = new Label(parent, SWT.NONE);
		label.setLayoutData(new GridData());
		label.setText(text);
		return label;
	}

	protected Text createEditableText(Composite parent, String defaultText) {
		Text text = new Text(parent, SWT.BORDER);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return text;
	}

	private void openDirectoryDialog() {
		try {
			DirectoryDialog dd = new DirectoryDialog(composite.getShell(),
					SWT.NONE);

			String destination = dd.open();
			if (destination != null) {
				destinationPathText.setText(destination);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	private boolean isPathValid(String path) {
		if (path == null || path.length() <= 0) {
			setErrorMessage(PublishingUIResources.invalidPathError_msg); //$NON-NLS-1$
			return false;
		}

		IPath ecPath = Path.fromOSString(path);
		boolean isValid = ecPath.isValidPath(path);
		if (!isValid) {
			setErrorMessage(PublishingUIResources.invalidPathError_msg); //$NON-NLS-1$
			return false;
		} else if (!StrUtil.isValidPublishPath(path)) {
			setErrorMessage(PublishingUIResources.invalidPathCharsError_msg); //$NON-NLS-1$
			return false;
		}

		setErrorMessage(null);
		return true;
	}

}
