package bndtools.editor.workspace;

import java.text.MessageFormat;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
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.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import aQute.bnd.header.Attrs;
import aQute.bnd.osgi.Constants;

public class PluginPropertiesPage extends WizardPage {

	private IConfigurationElement	configElement;
	private Attrs					properties	= new Attrs();
	private boolean					changed		= false;

	private Composite				mainComposite;
	private Composite				fieldContainer;
	private Text					txtPath;

	public PluginPropertiesPage() {
		super("pluginProperties");
	}

	@Override
	public void createControl(Composite parent) {
		setTitle("Plug-in Configuration");
		setDescription("Set configuration properties for the plug-in.");

		// Create controls
		mainComposite = new Composite(parent, SWT.NONE);

		Group group = new Group(mainComposite, SWT.NONE);
		group.setText("Properties");
		group.setLayout(new FillLayout());
		ScrolledComposite scroller = new ScrolledComposite(group, SWT.V_SCROLL);
		fieldContainer = new Composite(scroller, SWT.NONE);
		scroller.setMinSize(200, 200);
		scroller.setExpandVertical(true);
		scroller.setExpandHorizontal(true);
		scroller.setContent(fieldContainer);

		Label separator = new Label(mainComposite, SWT.SEPARATOR | SWT.HORIZONTAL);

		Composite classpathComposite = new Composite(mainComposite, SWT.NONE);
		new Label(classpathComposite, SWT.NONE).setText("Classpath:");
		txtPath = new Text(classpathComposite, SWT.BORDER);

		resetPropertyFields();

		String path = properties.get(Constants.PATH_DIRECTIVE);
		if (path != null)
			txtPath.setText(path);
		txtPath.addModifyListener(e -> {
			String path1 = txtPath.getText();
			if (path1 == null || path1.length() == 0)
				properties.remove(Constants.PATH_DIRECTIVE);
			else
				properties.put(Constants.PATH_DIRECTIVE, path1);
			changed = true;
		});

		// Layout
		GridLayout layout;
		GridData gd;

		layout = new GridLayout(1, false);
		mainComposite.setLayout(layout);

		gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		group.setLayoutData(gd);
		gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
		separator.setLayoutData(gd);
		gd = new GridData(SWT.FILL, SWT.FILL, true, false);
		classpathComposite.setLayoutData(gd);

		layout = new GridLayout(2, false);
		layout.verticalSpacing = 10;
		layout.horizontalSpacing = 10;
		fieldContainer.setLayout(layout);

		layout = new GridLayout(2, false);
		classpathComposite.setLayout(layout);
		gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
		txtPath.setLayoutData(gd);

		setControl(mainComposite);
	}

	void resetPropertyFields() {
		// Remove existing controls
		Control[] children = fieldContainer.getChildren();
		for (Control child : children)
			child.dispose();

		// Add new ones
		if (configElement != null) {
			IConfigurationElement[] propertyElements = configElement.getChildren("property");
			String path = configElement.getAttribute("path");
			String className = configElement.getAttribute("class");

			String summaryMessage = MessageFormat.format(
				"Found {0,choice,0#no properties|1#one property|1<{0} properties} for plug-in class {1}.",
				propertyElements.length, className);

			if (path != null) {
				properties.put(Constants.PATH_DIRECTIVE, path);
				txtPath.setText(path);
			}

			for (IConfigurationElement propertyElement : propertyElements) {
				final String name = propertyElement.getAttribute("name");
				String value = properties.get(name);

				String propertyType = propertyElement.getAttribute("type");
				String defaultStr = propertyElement.getAttribute("default");
				if (value == null && defaultStr != null) {
					value = defaultStr;
					properties.put(name, defaultStr);
				}

				Label label = new Label(fieldContainer, SWT.NONE);
				label.setText(name);

				if ("boolean".equals(propertyType)) {
					final Button button = new Button(fieldContainer, SWT.CHECK);
					button.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));

					button.setSelection("true".equalsIgnoreCase(value));

					button.addSelectionListener(new SelectionAdapter() {
						@Override
						public void widgetSelected(SelectionEvent e) {
							properties.put(name, button.getSelection() ? "true" : "false");
							changed = true;
						}
					});
				} else {
					final Text text = new Text(fieldContainer, SWT.BORDER);
					text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

					if (value != null)
						text.setText(value);

					text.addModifyListener(e -> {
						String value1 = text.getText();
						if (value1 == null || value1.length() == 0)
							properties.remove(name);
						else
							properties.put(name, value1);
						changed = true;
					});
				}

				String description = propertyElement.getAttribute("description");
				if (description != null) {
					ControlDecoration decoration = new ControlDecoration(label, SWT.RIGHT | SWT.CENTER);
					decoration.setShowHover(true);
					decoration.setDescriptionText(description);
					decoration.setImage(FieldDecorationRegistry.getDefault()
						.getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION)
						.getImage());
				}

				String deprecation = propertyElement.getAttribute("deprecated");
				if (deprecation != null) {
					ControlDecoration decoration = new ControlDecoration(label, SWT.LEFT | SWT.CENTER);
					decoration.setShowHover(true);
					decoration.setDescriptionText("Property deprecated: " + deprecation);
					decoration.setImage(FieldDecorationRegistry.getDefault()
						.getFieldDecoration(FieldDecorationRegistry.DEC_WARNING)
						.getImage());
				}
			}
			Label summaryLabel = new Label(fieldContainer, SWT.NONE);
			summaryLabel.setText(summaryMessage);
			summaryLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
		}
		mainComposite.layout(true, true);
	}

	public IConfigurationElement getConfigElement() {
		return configElement;
	}

	public void setConfigElement(IConfigurationElement configElement) {
		this.configElement = configElement;
		if (Display.getCurrent() != null && fieldContainer != null && !fieldContainer.isDisposed()) {
			resetPropertyFields();
		}
	}

	public void setProperties(Attrs properties) {
		this.properties = properties;
		if (Display.getCurrent() != null && fieldContainer != null && !fieldContainer.isDisposed()) {
			resetPropertyFields();
		}
	}

	public Attrs getProperties() {
		return properties;
	}

	public boolean isChanged() {
		return changed;
	}

}
