package bndtools.editor.pages;

import org.bndtools.core.ui.ExtendedFormEditor;
import org.bndtools.core.ui.IFormPageFactory;
import org.bndtools.core.ui.icons.Icons;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.plugin.AbstractUIPlugin;

import aQute.bnd.build.Workspace;
import aQute.bnd.build.model.BndEditModel;
import bndtools.Plugin;
import bndtools.central.Central;
import bndtools.editor.common.MDSashForm;
import bndtools.editor.project.AvailableBundlesPart;
import bndtools.editor.project.RepositorySelectionPart;
import bndtools.editor.project.RunBlacklistPart;
import bndtools.editor.project.RunBundlesPart;
import bndtools.editor.project.RunFrameworkPart;
import bndtools.editor.project.RunPropertiesPart;
import bndtools.editor.project.RunRequirementsPart;
import bndtools.utils.MessageHyperlinkAdapter;

public class ProjectRunPage extends FormPage {

	private final BndEditModel				model;

	private final Image						imgBndLayout		= Icons.desc("bnd.workspace.bndlayout")
		.createImage();
	private final Image						imgStandaloneLayout	= Icons.desc("bnd.workspace.standalone")
		.createImage();

	public static final IFormPageFactory	FACTORY_PROJECT		= new IFormPageFactory() {
																	@Override
																	public IFormPage createPage(
																		ExtendedFormEditor editor, BndEditModel model,
																		String id) throws IllegalArgumentException {
																		//
																		// Re-enabling
																		// Resolve
																		// see:
																		// https://github.com/bndtools/bndtools/issues/651
																		// There
																		// might
																		// be
																		// some
																		// issues
																		// around
																		// this
																		// but
																		// we
																		// have
																		// to
																		// figure
																		// them
																		// out
																		//
																		return new ProjectRunPage(editor, model, id,
																			"Run", true);
																	}

																	@Override
																	public boolean supportsMode(Mode mode) {
																		return mode == Mode.project;
																	}
																};

	public static final IFormPageFactory	FACTORY_BNDRUN		= new IFormPageFactory() {
																	@Override
																	public IFormPage createPage(
																		ExtendedFormEditor editor, BndEditModel model,
																		String id) throws IllegalArgumentException {
																		return new ProjectRunPage(editor, model, id,
																			"Run", true);
																	}

																	@Override
																	public boolean supportsMode(Mode mode) {
																		return mode == Mode.bndrun;
																	}
																};

	private final boolean					supportsResolve;

	public ProjectRunPage(FormEditor editor, BndEditModel model, String id, String title, boolean supportsResolve) {
		super(editor, id, title);
		this.model = model;
		this.supportsResolve = supportsResolve;
	}

	@Override
	protected void createFormContent(IManagedForm managedForm) {
		managedForm.setInput(model);

		FormToolkit tk = managedForm.getToolkit();
		final ScrolledForm form = managedForm.getForm();
		form.setText("Resolve/Run");

		Central.onWorkspaceAsync(workspace -> updateFormImage(form));

		tk.decorateFormHeading(form.getForm());
		form.getForm()
			.addMessageHyperlinkListener(new MessageHyperlinkAdapter(getEditor()));

		// Toolbar Actions
		RunAction runAction = new RunAction(this, "run");
		runAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "icons/run.gif"));
		runAction.setText("Run OSGi");
		ActionContributionItem runContrib = new ActionContributionItem(runAction);
		runContrib.setMode(ActionContributionItem.MODE_FORCE_TEXT);
		form.getToolBarManager()
			.add(runContrib);

		RunAction debugAction = new RunAction(this, "debug");
		debugAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "icons/debug.gif"));
		debugAction.setText("Debug OSGi");
		ActionContributionItem debugContrib = new ActionContributionItem(debugAction);
		debugContrib.setMode(ActionContributionItem.MODE_FORCE_TEXT);
		form.getToolBarManager()
			.add(debugContrib);

		ExportAction exportAction = new ExportAction(getEditorSite().getShell(), getEditor(), model);
		exportAction
			.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "icons/run_export.png"));
		exportAction.setText("Export");
		ActionContributionItem exportContrib = new ActionContributionItem(exportAction);
		exportContrib.setMode(ActionContributionItem.MODE_FORCE_TEXT);
		if (exportAction.shouldEnable())
			form.getToolBarManager()
				.add(exportContrib);

		form.getToolBarManager()
			.update(true);

		GridLayout gl;
		GridData gd;

		// Create Controls
		final Composite body = form.getBody();

		MDSashForm sashForm = new MDSashForm(body, SWT.HORIZONTAL, managedForm);
		sashForm.setSashWidth(6);
		tk.adapt(sashForm);

		final Composite left = tk.createComposite(sashForm);
		gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		left.setLayoutData(gd);
		gl = new GridLayout(1, true);
		left.setLayout(gl);

		final Composite right = tk.createComposite(sashForm);
		gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		right.setLayoutData(gd);
		gl = new GridLayout(1, true);
		right.setLayout(gl);

		// First column
		RepositorySelectionPart reposPart = new RepositorySelectionPart(getEditor(), left, tk,
			ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE);
		managedForm.addPart(reposPart);
		gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		gd.widthHint = 50;
		gd.heightHint = 50;
		reposPart.getSection()
			.setLayoutData(PageLayoutUtils.createCollapsed());

		AvailableBundlesPart availableBundlesPart = new AvailableBundlesPart(left, tk,
			ExpandableComposite.TITLE_BAR | ExpandableComposite.EXPANDED);
		managedForm.addPart(availableBundlesPart);
		gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		gd.widthHint = 50;
		gd.heightHint = 50;
		availableBundlesPart.getSection()
			.setLayoutData(PageLayoutUtils.createExpanded());

		RunFrameworkPart runFwkPart = new RunFrameworkPart(left, tk,
			ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED);
		managedForm.addPart(runFwkPart);
		gd = new GridData(SWT.FILL, SWT.FILL, true, false);
		runFwkPart.getSection()
			.setLayoutData(gd);

		RunPropertiesPart runPropertiesPart = new RunPropertiesPart(left, tk,
			ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE);
		managedForm.addPart(runPropertiesPart);
		gd = new GridData(SWT.FILL, SWT.FILL, true, false);
		runPropertiesPart.getSection()
			.setLayoutData(gd);

		// SECOND COLUMN
		if (supportsResolve) {
			RunRequirementsPart requirementsPart = new RunRequirementsPart(right, tk, ExpandableComposite.TITLE_BAR
				| ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED | Section.DESCRIPTION);
			managedForm.addPart(requirementsPart);
			requirementsPart.getSection()
				.setLayoutData(PageLayoutUtils.createExpanded());
			requirementsPart.getSection()
				.addExpansionListener(new ResizeExpansionAdapter(requirementsPart.getSection()));

			RunBlacklistPart blacklistPart = new RunBlacklistPart(right, tk, ExpandableComposite.TITLE_BAR
				| ExpandableComposite.TWISTIE | ExpandableComposite.COMPACT | Section.DESCRIPTION);
			managedForm.addPart(blacklistPart);
			blacklistPart.getSection()
				.setLayoutData(PageLayoutUtils.createCollapsed());
			blacklistPart.getSection()
				.addExpansionListener(new ResizeExpansionAdapter(blacklistPart.getSection()));

			RunBundlesPart runBundlesPart = new RunBundlesPart(right, tk,
				ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE);
			managedForm.addPart(runBundlesPart);
			runBundlesPart.getSection()
				.setLayoutData(PageLayoutUtils.createCollapsed());
			runBundlesPart.getSection()
				.addExpansionListener(new ResizeExpansionAdapter(runBundlesPart.getSection()));
		} else {
			RunBundlesPart runBundlesPart = new RunBundlesPart(right, tk,
				ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED);
			managedForm.addPart(runBundlesPart);
			runBundlesPart.getSection()
				.setLayoutData(PageLayoutUtils.createExpanded());
			runBundlesPart.getSection()
				.addExpansionListener(new ResizeExpansionAdapter(runBundlesPart.getSection()));
		}

		// Listeners
		model.addPropertyChangeListener(BndEditModel.PROP_WORKSPACE, evt -> Display.getDefault()
			.asyncExec(() -> updateFormImage(form)));

		sashForm.setWeights(new int[] {
			1, 1
		});
		sashForm.hookResizeListener();
		body.setLayout(new FillLayout());
	}

	@Override
	public void dispose() {
		super.dispose();
		imgBndLayout.dispose();
		imgStandaloneLayout.dispose();
	}

	private void updateFormImage(final ScrolledForm form) {
		Workspace ws = model.getWorkspace();
		switch (ws.getLayout()) {
			case BND :
				form.setImage(imgBndLayout);
				break;
			case STANDALONE :
				form.setImage(imgStandaloneLayout);
				break;
			default :
		}
	}
}
