/*
 * (c) Copyright Sysdeo SA 2001, 2002.
 * All Rights Reserved.
 */

package com.sysdeo.eclipse.tomcat;

import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_CHOOSECONFMODE_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_CHOOSEVERSION_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_CONFIGFILE_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_CONTEXTFILES_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_CONTEXTSDIR_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_HOME_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_SERVERXML_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_VERSION7_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_VERSION8_LABEL;
import static com.sysdeo.eclipse.tomcat.TomcatPluginResources.PREF_PAGE_VERSION9_LABEL;

import java.io.File;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.preference.DirectoryFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.preference.RadioGroupFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.osgi.service.prefs.BackingStoreException;

import com.sysdeo.eclipse.tomcat.editors.TomcatDirectoryFieldEditor;
import com.sysdeo.eclipse.tomcat.editors.TomcatFileFieldEditor;

/**
 * TomcatPreferencePage
 *
 */
public class TomcatPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, IPropertyChangeListener {

	/** RadioGroupFieldEditor */
	private RadioGroupFieldEditor version;
	/** DirectoryFieldEditor */
	private DirectoryFieldEditor home;
	/** TomcatDirectoryFieldEditor */
	private TomcatDirectoryFieldEditor contextsDir;
	/** TomcatFileFieldEditor */
	private TomcatFileFieldEditor configFile;
	/** ModifyListener */
	private RadioGroupFieldEditor configMode;
	/** selectedVersion */
	private String selectedVersion;
	/** oldVersion */
	private String oldVersion;
	/** configLocationGroup */
	private Composite configLocationGroup;

	/**
	 * Constructor
	 */
	public TomcatPreferencePage() {
		super();
		setPreferenceStore(TomcatLauncherPlugin.getDefault().getPreferenceStore());
	}

	/**
	 * @see PreferencePage#createContents(Composite)
	 */
	@Override
	protected Control createContents(final Composite composite) {

		this.oldVersion = TomcatLauncherPlugin.getTomcatVersion();
		this.version = new RadioGroupFieldEditor(
				TomcatPluginResources.TOMCAT_PREF_VERSION_KEY,
				PREF_PAGE_CHOOSEVERSION_LABEL, 1,
				new String[][] {
					// {PREF_PAGE_VERSION3_LABEL, TomcatLauncherPlugin.TOMCAT_VERSION3},
					// {PREF_PAGE_VERSION4_LABEL, TomcatLauncherPlugin.TOMCAT_VERSION4},
					// {PREF_PAGE_VERSION4_1_LABEL, TomcatLauncherPlugin.TOMCAT_VERSION41},
					// {PREF_PAGE_VERSION5_LABEL, TomcatLauncherPlugin.TOMCAT_VERSION5},
					// {PREF_PAGE_VERSION6_LABEL, TomcatLauncherPlugin.TOMCAT_VERSION6},

					{PREF_PAGE_VERSION7_LABEL, TomcatPluginResources.TOMCAT_VERSION7},
					{PREF_PAGE_VERSION8_LABEL, TomcatPluginResources.TOMCAT_VERSION8},
					{PREF_PAGE_VERSION9_LABEL, TomcatPluginResources.TOMCAT_VERSION9}
				},
				composite, true);

		Group homeGroup = new Group(composite, SWT.NONE);
		this.home = new DirectoryFieldEditor(
				TomcatPluginResources.TOMCAT_PREF_HOME_KEY,
				PREF_PAGE_HOME_LABEL, homeGroup);

		//blank
		insertBlank(composite);

		Group modeGroup = new Group(composite, SWT.NONE);
		modeGroup.setLayout(new GridLayout(1, false));

		Composite configGroup = new Composite(modeGroup, SWT.NULL);
		this.configMode = new RadioGroupFieldEditor(
				TomcatPluginResources.TOMCAT_PREF_CONFMODE_KEY,
				PREF_PAGE_CHOOSECONFMODE_LABEL, 1,
				new String[][] {
					{PREF_PAGE_SERVERXML_LABEL, TomcatPluginResources.SERVERXML_MODE},
					{PREF_PAGE_CONTEXTFILES_LABEL, TomcatPluginResources.CONTEXTFILES_MODE},
				},
				configGroup, false);

		//blank
		insertBlank(composite);

		this.configLocationGroup = new Composite(modeGroup, SWT.NULL);
		this.configFile = new TomcatFileFieldEditor(
				TomcatPluginResources.TOMCAT_PREF_CONFIGFILE_KEY,
				PREF_PAGE_CONFIGFILE_LABEL,
				this.configLocationGroup);

		this.contextsDir = new TomcatDirectoryFieldEditor(
				TomcatPluginResources.TOMCAT_PREF_CONTEXTSDIR_KEY,
				PREF_PAGE_CONTEXTSDIR_LABEL,
				this.configLocationGroup);

		this.home.setPropertyChangeListener(this);

		//blank
		insertBlank(composite);

		initLayoutAndData(homeGroup, 3);
		initLayoutAndData(modeGroup, 1);
		initLayoutAndData(this.configLocationGroup, 3);

		initializeField();

		return composite;
	}

	/**
	 * initialize Field
	 */
	private void initializeField() {

		initField(this.version);
		this.version.setPropertyChangeListener(this);

		initField(this.home);
		initField(this.configMode);
		modeChanged(this.configLocationGroup,
						getPreferenceStore().getString(TomcatPluginResources.TOMCAT_PREF_CONFMODE_KEY));

		this.configMode.setPropertyChangeListener(this);

		initField(this.configFile);
		if (this.configFile.getStringValue().length() == 0) {
			computeConfigFile();
		}
		initField(this.contextsDir);
		if (this.contextsDir.getStringValue().length() == 0) {
			computeContextsDir();
		}

	}

	/**
	 * create blank
	 * @param composite Composite
	 */
	private void insertBlank(final Composite composite) {
		Label lbl = new Label(composite, SWT.NULL);
		lbl.setParent(composite);
	}

	/**
	 * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
	 */
	@Override
	public void propertyChange(final PropertyChangeEvent event) {
		if (event.getSource() == this.home) {
			if (event.getProperty().equals(FieldEditor.VALUE)) {
				computeConfigFile();
				computeContextsDir();
			}
		} else if (event.getSource() == this.version) {
			if (event.getProperty().equals(FieldEditor.VALUE)) {
				String value = (String)event.getNewValue();
				versionChanged(value);
			}
		} else if (event.getSource() == this.configMode) {
			if (event.getProperty().equals(FieldEditor.VALUE)) {
				String value = (String)event.getNewValue();
				modeChanged(this.configLocationGroup, value);
			}
		}
	}

	/**
	 * @see IWorkbenchPreferencePage#init(IWorkbench)
	 */
	@Override
	public void init(final IWorkbench workbench) {
		return;
	}

	/**
	 * @see org.eclipse.jface.preference.PreferencePage#performOk()
	 */
	@Override
	public boolean performOk() {
		this.version.store();
		this.home.store();
		this.configFile.store();
		this.configMode.store();
		this.contextsDir.store();
		TomcatLauncherPlugin.initTomcatClasspathVariable();
		try {
			InstanceScope.INSTANCE.getNode(TomcatPluginResources.PLUGIN_ID).flush();
		} catch (final BackingStoreException e) {
			TomcatLauncherPlugin.log(e);
			return false;
		}
		// TomcatLauncherPlugin.getDefault().savePluginPreferences();

		if (!this.oldVersion.equals(TomcatLauncherPlugin.getTomcatVersion())) {
			this.updateTomcatProjectsBuildPath();
		}
		return true;
	}

	/**
	 * updateTomcatProjectsBuildPath
	 */
	private void updateTomcatProjectsBuildPath() {
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

		try {
			for (final IProject project : root.getProjects()) {
				if (project.hasNature(TomcatPluginResources.NATURE_ID)) {
					TomcatProject.create(project).addTomcatJarToProjectClasspath();
				}
			}
		} catch (final CoreException e) {
			// ignore update if there is an exception
			TomcatLauncherPlugin.log(e.getMessage());
		}
	}

	/**
	 *
	 * @param field FieldEditor
	 */
	private void initField(final FieldEditor field) {
		field.setPreferenceStore(getPreferenceStore());
		field.setPage(this);
		field.load();
	}

	/**
	 * computeConfigFile
	 */
	private void computeConfigFile() {
		this.configFile.setStringValue(
						this.home.getStringValue() + File.separator + "conf" + File.separator + "server.xml");
	}

	/**
	 * computeContextsDir
	 */
	private void computeContextsDir() {
		if (this.selectedVersion == null) {
			this.selectedVersion = TomcatLauncherPlugin.getDefault().getPreferenceStore().
					getString(TomcatPluginResources.TOMCAT_PREF_VERSION_KEY);
		}

		String contextDirName = this.home.getStringValue() + File.separator + "conf"
						+ File.separator + "Catalina" + File.separator + "localhost";
		checkOrCreateDefaultContextDir();
		this.contextsDir.setStringValue(contextDirName);
	}

	/**
	 * Since Tomcat 6, conf/Catalina/host does not exist after installation
	 * @return boolean
	 */
	private boolean checkOrCreateDefaultContextDir() {
		boolean ret = true;
		String confDirName = this.home.getStringValue() + File.separator + "conf";
		File confDir = new File(confDirName);
		if (confDir.exists()) {
			String catalinaDirName = confDirName + File.separator + "Catalina";
			File catalinaDir = new File(catalinaDirName);
			ret = catalinaDir.mkdir();
			if (catalinaDir.exists()) {
				String localhostDirName = catalinaDirName + File.separator + "localhost";
				File localhostDir = new File(localhostDirName);
				ret = localhostDir.mkdir() && ret;
			}
		}
		return ret;
	}

	/**
	 *
	 * @param composite Composite
	 * @param value String
	 */
	private void modeChanged(final Composite composite, final String value) {
		if (value.equals(TomcatPluginResources.SERVERXML_MODE)) {
			this.contextsDir.setEnabled(false, composite);
			this.configFile.setEnabled(true, composite);
		} else {
			this.contextsDir.setEnabled(true, composite);
			this.configFile.setEnabled(false, composite);
		}

		// Refresh error message
		this.configFile.valueChanged();
		this.contextsDir.valueChanged();
	}

	/**
	 *
	 * @param value String
	 */
	private void versionChanged(final String value) {
		this.selectedVersion = value;
		computeContextsDir();
	}

	/**
	 *
	 * @param aGroup Composite
	 * @param numColumns int
	 */
	private void initLayoutAndData(final Composite aGroup, final int numColumns) {
		GridLayout gl = new GridLayout(numColumns, false);
		aGroup.setLayout(gl);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 1;
		gd.widthHint = 400;
		aGroup.setLayoutData(gd);
	}
}
