/*******************************************************************************
 * Copyright (c) 2009, 2022 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Christoph Läubrich 	[Bug 567506] - TargetLocationsGroup.handleEdit() should activate bundles if necessary
 *     						[Bug 568865] - add advanced editing capabilities for custom target platforms
 *******************************************************************************/
package org.eclipse.pde.internal.ui.shared.target;

import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.pde.core.target.*;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.SWTFactory;
import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
import org.eclipse.pde.internal.ui.editor.targetdefinition.TargetEditor;
import org.eclipse.pde.internal.ui.wizards.target.TargetDefinitionContentPage;
import org.eclipse.pde.ui.target.ITargetLocationHandler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.progress.UIJob;

/**
 * UI part that can be added to a dialog or to a form editor. Contains a table
 * displaying the bundle containers of a target definition. Also has buttons to
 * add, edit and remove bundle containers of varying types.
 *
 * @see TargetEditor
 * @see TargetDefinitionContentPage
 * @see ITargetDefinition
 * @see ITargetLocation
 */
public class TargetLocationsGroup {

	private static final String BUTTON_STATE = "ButtonState"; //$NON-NLS-1$

	private enum DeleteButtonState {
		NONE, REMOVE, ENABLE, DISABLE, TOGGLE;

		static DeleteButtonState computeState(boolean canRemove, boolean canEnable, boolean canDisable) {
			if (canRemove) {
				if (canEnable || canDisable) {
					// a mixture of actions is currently selected
					return NONE;
				}
				return REMOVE;
			}
			if (canEnable) {
				if (canDisable) {
					return TOGGLE;
				}
				return ENABLE;
			} else if (canDisable) {
				return DISABLE;
			}
			return NONE;
		}
	}

	private TreeViewer fTreeViewer;
	private Action fCopySelectionAction;
	private Button fAddButton;
	private Button fEditButton;
	private Button fRemoveButton;
	private Button fUpdateButton;
	private Button fReloadButton;
	private Button fExpandCollapseButton;
	private Button fShowContentButton;

	private ITargetDefinition fTarget;
	private ListenerList<ITargetChangedListener> fChangeListeners = new ListenerList<>();
	private ListenerList<ITargetChangedListener> fReloadListeners = new ListenerList<>();
	private static final TargetLocationHandlerAdapter ADAPTER = new TargetLocationHandlerAdapter();

	/**
	 * Creates this part using the form toolkit and adds it to the given
	 * composite.
	 *
	 * @param parent
	 *            parent composite
	 * @param toolkit
	 *            toolkit to create the widgets with
	 * @return generated instance of the table part
	 */
	public static TargetLocationsGroup createInForm(Composite parent, FormToolkit toolkit) {
		TargetLocationsGroup contentTable = new TargetLocationsGroup();
		contentTable.createFormContents(parent, toolkit);
		return contentTable;
	}

	/**
	 * Creates this part using standard dialog widgets and adds it to the given
	 * composite.
	 *
	 * @param parent
	 *            parent composite
	 * @return generated instance of the table part
	 */
	public static TargetLocationsGroup createInDialog(Composite parent) {
		TargetLocationsGroup contentTable = new TargetLocationsGroup();
		contentTable.createDialogContents(parent);
		return contentTable;
	}

	/**
	 * Private constructor, use one of {@link #createInDialog(Composite)} or
	 * {@link #createInForm(Composite, FormToolkit)}.
	 */
	private TargetLocationsGroup() {

	}

	/**
	 * Adds a listener to the set of listeners that will be notified when the
	 * bundle containers are modified. This method has no effect if the listener
	 * has already been added.
	 *
	 * @param listener
	 *            target changed listener to add
	 */
	public void addTargetChangedListener(ITargetChangedListener listener) {
		fChangeListeners.add(listener);
	}

	/**
	 * Adds a listener to the set of listeners that will be notified when target
	 * is reloaded. This method has no effect if the listener has already been
	 * added.
	 *
	 * @param listener
	 *            target changed listener to add
	 */
	public void addTargetReloadListener(ITargetChangedListener listener) {
		fReloadListeners.add(listener);
	}

	/**
	 * Creates the part contents from a toolkit
	 *
	 * @param parent
	 *            parent composite
	 * @param toolkit
	 *            form toolkit to create widgets
	 */
	private void createFormContents(Composite parent, FormToolkit toolkit) {
		Composite comp = toolkit.createComposite(parent);
		comp.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 2));
		comp.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL));

		Tree atree = toolkit.createTree(comp, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
		atree.setLayout(new GridLayout());
		GridData gd = new GridData(GridData.FILL_BOTH);
		atree.setLayoutData(gd);
		initializeTree(atree);

		Composite buttonComp = toolkit.createComposite(comp);
		GridLayout layout = new GridLayout();
		layout.marginWidth = layout.marginHeight = 0;
		buttonComp.setLayout(layout);
		buttonComp.setLayoutData(new GridData(GridData.FILL_VERTICAL));

		fAddButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Add, SWT.PUSH);
		fEditButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Edit, SWT.PUSH);
		fRemoveButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Remove, SWT.PUSH);
		fUpdateButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Update, SWT.PUSH);
		fUpdateButton.setToolTipText(Messages.TargetLocationsGroup_update);
		fReloadButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Reload, SWT.PUSH);
		fReloadButton.setToolTipText(Messages.TargetLocationsGroup_reload);
		fExpandCollapseButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_Btn_Text_ExpandAll, SWT.PUSH);

		fShowContentButton = toolkit.createButton(comp, Messages.TargetLocationsGroup_1, SWT.CHECK);

		initializeTreeViewer(atree);
		initializeButtons();

		toolkit.paintBordersFor(comp);
	}

	/**
	 * Creates the part contents using SWTFactory
	 *
	 * @param parent
	 *            parent composite
	 */
	private void createDialogContents(Composite parent) {
		Composite comp = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_BOTH, 0, 0);

		Tree atree = new Tree(comp, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.MULTI);
		atree.setFont(comp.getFont());
		atree.setLayout(new GridLayout());
		GridData gd = new GridData(GridData.FILL_BOTH);
		gd.widthHint = 200;
		atree.setLayoutData(gd);
		initializeTree(atree);

		Composite buttonComp = SWTFactory.createComposite(comp, 2, 1, GridData.FILL_BOTH);
		GridLayout layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		buttonComp.setLayout(layout);
		buttonComp.setLayoutData(new GridData(GridData.FILL_VERTICAL));

		fAddButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Add, null);
		fEditButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Edit, null);
		fRemoveButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Remove, null);
		fUpdateButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Update, null);
		fReloadButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_Btn_Text_Reload, null);
		fExpandCollapseButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_Btn_Text_ExpandAll, null);

		fShowContentButton = SWTFactory.createCheckButton(comp, Messages.TargetLocationsGroup_1, null, false, 2);

		initializeTreeViewer(atree);
		initializeButtons();
	}

	private void initializeTree(Tree tree) {
		tree.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.DEL && fRemoveButton.getEnabled()) {
					handleRemove();
				} else if (e.keyCode == 'c' && (e.stateMask & SWT.CTRL) != 0) {
					fCopySelectionAction.run();
				}
			}
		});
	}

	/**
	 * Sets up the tree viewer using the given tree
	 */
	private void initializeTreeViewer(Tree tree) {
		fTreeViewer = new TreeViewer(tree);
		fTreeViewer.setContentProvider(new TargetLocationContentProvider());
		fTreeViewer.setLabelProvider(new StyledBundleLabelProvider(true, false));
		fTreeViewer.setComparator(new ViewerComparator() {
			@Override
			public int compare(Viewer viewer, Object e1, Object e2) {
				// Status at the end of the list
				if (e1 instanceof IStatus && !(e2 instanceof IStatus)) {
					return 1;
				}
				if (e2 instanceof IStatus && !(e1 instanceof IStatus)) {
					return -1;
				}
				return super.compare(viewer, e1, e2);
			}
		});
		fTreeViewer.addSelectionChangedListener(event -> updateButtons());
		fTreeViewer.addDoubleClickListener(event -> {
			if (!event.getSelection().isEmpty()) {
				handleEdit();
			}
		});
		fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);

		createContextMenu(fTreeViewer.getTree());
		fTreeViewer.getTree().addMouseListener(new MouseListener() {
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				setExpandCollapseState();
			}
			@Override
			public void mouseDown(MouseEvent e) {
			}
			@Override
			public void mouseUp(MouseEvent e) {
				setExpandCollapseState();
			}

		});
		fTreeViewer.getTree().addKeyListener(new KeyListener() {

			@Override
			public void keyPressed(KeyEvent e) {

			}

			@Override
			public void keyReleased(KeyEvent e) {
				setExpandCollapseState();
			}

		});
	}

	private void setExpandCollapseState() {
		if (fTreeViewer == null)
			return;
		if (fTreeViewer.getVisibleExpandedElements().length == 0) {
			fExpandCollapseButton.setText(Messages.BundleContainerTable_Btn_Text_ExpandAll);
		} else {
			fExpandCollapseButton.setText(Messages.BundleContainerTable_Btn_Text_CollapseAll);
		}

	}
	private void createContextMenu(Tree tree) {
		fCopySelectionAction = new CopyTreeSelectionAction(tree);

		MenuManager menuManager = new MenuManager();
		menuManager.add(fCopySelectionAction);

		Menu menu = menuManager.createContextMenu(tree);
		tree.setMenu(menu);
	}

	/**
	 * Sets up the buttons, the button fields must already be created before
	 * calling this method
	 */
	private void initializeButtons() {
		fAddButton.addSelectionListener(widgetSelectedAdapter(e -> handleAdd()));
		fAddButton.setLayoutData(new GridData());
		SWTFactory.setButtonDimensionHint(fAddButton);

		fEditButton.addSelectionListener(widgetSelectedAdapter(e -> handleEdit()));
		fEditButton.setLayoutData(new GridData());
		fEditButton.setEnabled(false);
		SWTFactory.setButtonDimensionHint(fEditButton);

		fRemoveButton.addSelectionListener(widgetSelectedAdapter(e -> handleRemove()));
		fRemoveButton.setLayoutData(new GridData());
		fRemoveButton.setEnabled(false);
		SWTFactory.setButtonDimensionHint(fRemoveButton);

		fUpdateButton.addSelectionListener(widgetSelectedAdapter(e -> handleUpdate()));
		fUpdateButton.setLayoutData(new GridData());
		fUpdateButton.setEnabled(false);
		SWTFactory.setButtonDimensionHint(fUpdateButton);

		fReloadButton.addSelectionListener(widgetSelectedAdapter(e -> handleReload()));
		fReloadButton.setLayoutData(new GridData());
		fReloadButton.setEnabled(true);
		SWTFactory.setButtonDimensionHint(fReloadButton);

		fExpandCollapseButton.addSelectionListener(widgetSelectedAdapter(e -> toggleCollapse()));
		fExpandCollapseButton.setLayoutData(new GridData());
		fExpandCollapseButton.setEnabled(false);
		SWTFactory.setButtonDimensionHint(fExpandCollapseButton);

		fShowContentButton.addSelectionListener(widgetSelectedAdapter(e -> {
			((TargetLocationContentProvider) fTreeViewer.getContentProvider())
					.setShowLocationContent(fShowContentButton.getSelection());
			fTreeViewer.refresh();
			fTreeViewer.expandAll();
			fExpandCollapseButton.setText(Messages.BundleContainerTable_Btn_Text_CollapseAll);
		}));
		fShowContentButton.setLayoutData(new GridData());
		SWTFactory.setButtonDimensionHint(fShowContentButton);
	}

	/**
	 * Sets the target definition model to use as input for the tree, can be
	 * called with different models to change the tree's input.
	 *
	 * @param target
	 *            target model
	 */
	public void setInput(ITargetDefinition target) {
		fTarget = target;
		boolean isCollapsed = fTreeViewer.getVisibleExpandedElements().length == 0;
		fTreeViewer.setInput(fTarget);
		if (isCollapsed)
			fTreeViewer.collapseAll();
		updateButtons();
	}

	private void handleAdd() {
		AddBundleContainerWizard wizard = new AddBundleContainerWizard(fTarget);
		Shell parent = fTreeViewer.getTree().getShell();
		WizardDialog dialog = new WizardDialog(parent, wizard);
		if (dialog.open() != Window.CANCEL) {
			contentsChanged(false);
			fTreeViewer.refresh();
			updateButtons();
		}
	}

	private void handleEdit() {
		ITreeSelection selection = fTreeViewer.getStructuredSelection();
		TreePath[] paths = selection.getPaths();
		if (paths.length == 1) {
			IWizard editWizard = ADAPTER.getEditWizard(fTarget, paths[0]);
			if (editWizard != null) {
				Shell parent = fTreeViewer.getTree().getShell();
				WizardDialog wizard = new WizardDialog(parent, editWizard);
				if (wizard.open() == Window.OK) {
					updateXML();
					contentsChanged(false);
					fTreeViewer.refresh();
					updateButtons();
				}
			}
		}
	}

	private void updateXML() {
		fTarget.setTargetLocations(fTarget.getTargetLocations());
	}

	private void handleRemove() {
		ITreeSelection selection = fTreeViewer.getStructuredSelection();
		DeleteButtonState state = (DeleteButtonState) Objects.requireNonNullElse(fRemoveButton.getData(BUTTON_STATE),
				DeleteButtonState.NONE);
		if (selection.isEmpty() || state == DeleteButtonState.NONE) {
			fRemoveButton.setEnabled(false);
			return;
		}
		IStatus tstatus = fTarget.getStatus();
		IStatus status;
		if (state == DeleteButtonState.REMOVE) {
			status = log(ADAPTER.remove(fTarget, selection.getPaths()));
		} else {
			status = log(ADAPTER.toggle(fTarget, selection.getPaths()));
		}
		boolean forceReload = (tstatus != null && !tstatus.isOK())
				|| (status != null && status.isOK() && status.getCode() == ITargetLocationHandler.STATUS_FORCE_RELOAD);
		updateXML();
		contentsChanged(forceReload);
		fTreeViewer.refresh();
		updateButtons();
	}

	private void handleUpdate() {
		ITreeSelection selection = fTreeViewer.getStructuredSelection();
		if (selection.isEmpty()) {
			fUpdateButton.setEnabled(false);
			return;
		}
		List<IJobFunction> updateActions = Collections
				.singletonList(monitor -> log(ADAPTER.update(fTarget, selection.getPaths(), monitor)));
		JobChangeAdapter listener = new JobChangeAdapter() {
			@Override
			public void done(final IJobChangeEvent event) {
				UIJob job = new UIJob(Messages.UpdateTargetJob_UpdateJobName) {
					@Override
					public IStatus runInUIThread(IProgressMonitor monitor) {
						IStatus result = event.getJob().getResult();
						if (!result.isOK()) {
							if (!fTreeViewer.getControl().isDisposed()) {
								ErrorDialog.openError(fTreeViewer.getTree().getShell(),
										Messages.TargetLocationsGroup_TargetUpdateErrorDialog, result.getMessage(),
										result);
							}
						} else if (result.getCode() != ITargetLocationHandler.STATUS_CODE_NO_CHANGE) {
							// Update was successful and changed the target, if
							// dialog/editor still open, update it
							if (!fTreeViewer.getControl().isDisposed()) {
								contentsChanged(true);
								fTreeViewer.refresh(true);
								updateButtons();
							}

							// If the target is the current platform, run a load
							// job for the user
							try {
								ITargetPlatformService service = PDECore.getDefault()
										.acquireService(ITargetPlatformService.class);
								if (service != null) {
									ITargetHandle currentTarget = service.getWorkspaceTargetHandle();
									if (fTarget.getHandle().equals(currentTarget))
										LoadTargetDefinitionJob.load(fTarget);
								}
							} catch (CoreException e) {
								// do nothing if we could not set the current
								// target.
							}
						}
						return Status.OK_STATUS;
					}
				};
				job.schedule();
			}
		};
		UpdateTargetJob.update(updateActions, listener);
	}

	private void updateButtons() {

		ITreeSelection selection = fTreeViewer.getStructuredSelection();
		if (selection.isEmpty()) {
			fRemoveButton.setEnabled(false);
			fRemoveButton.setText(Messages.BundleContainerTable_Btn_Text_Remove);
			fRemoveButton.setData(BUTTON_STATE, DeleteButtonState.NONE);
			fUpdateButton.setEnabled(false);
			fEditButton.setEnabled(false);
			if(fTreeViewer !=null) {
				setExpandCollapseState();
			}
			return;
		}
		boolean canRemove = false;
		boolean canEdit = false;
		boolean canUpdate = false;
		boolean canEnable = false;
		boolean canDisable = false;

		TreePath[] paths = selection.getPaths();
		for (TreePath path : paths) {
			canRemove |= ADAPTER.canRemove(fTarget, path);
			canDisable |= ADAPTER.canDisable(fTarget, path);
			canEnable |= ADAPTER.canEnable(fTarget, path);
			canUpdate |= ADAPTER.canUpdate(fTarget, path);
			canEdit = paths.length == 1 && ADAPTER.canEdit(fTarget, path);
		}
		fEditButton.setEnabled(canEdit);
		fUpdateButton.setEnabled(canUpdate);
		DeleteButtonState state = DeleteButtonState.computeState(canRemove, canEnable, canDisable);
		switch (state)
			{
			case DISABLE:
				fRemoveButton.setText(Messages.BundleContainerTable_Btn_Text_Disable);
				break;
			case ENABLE:
				fRemoveButton.setText(Messages.BundleContainerTable_Btn_Text_Enable);
				break;
			case TOGGLE:
				fRemoveButton.setText(Messages.BundleContainerTable_Btn_Text_Toggle);
				break;
			default:
				fRemoveButton.setText(Messages.BundleContainerTable_Btn_Text_Remove);
				break;
			}
		fRemoveButton.setEnabled(state != DeleteButtonState.NONE);
		fRemoveButton.setData(BUTTON_STATE, state);
	}

	private void handleReload() {
		log(ADAPTER.reload(fTarget, fTarget.getTargetLocations(), new NullProgressMonitor()));
		Job job = new UIJob("Reloading...") { //$NON-NLS-1$
			@Override
			public IStatus runInUIThread(IProgressMonitor monitor) {
				contentsReload();
				return Status.OK_STATUS;
			}
		};
		job.schedule();

	}

	private void toggleCollapse() {
		if (fTreeViewer == null)
			return;
		if (fTreeViewer.getVisibleExpandedElements().length == 0) {
			fTreeViewer.expandAll();
			fExpandCollapseButton.setText(Messages.BundleContainerTable_Btn_Text_CollapseAll);
		} else {
			fTreeViewer.collapseAll();
			fExpandCollapseButton.setText(Messages.BundleContainerTable_Btn_Text_ExpandAll);
		}

	}

	/**
	 * Informs the reporter for this table that something has changed and is
	 * dirty.
	 */
	private void contentsChanged(boolean force) {
		for (ITargetChangedListener listener : fChangeListeners) {
			listener.contentsChanged(fTarget, this, true, force);
		}
	}

	/**
	 * Reloads the target
	 *
	 */
	private void contentsReload() {
		for (ITargetChangedListener listener : fReloadListeners) {
			listener.contentsChanged(fTarget, this, true, true);
		}

	}

	private static IStatus log(IStatus status) {
		if (status != null && !status.isOK()) {
			PDEPlugin.log(status);
		}
		return status;
	}

	public void setExpandCollapseState(boolean b) {
		if (fExpandCollapseButton != null)
			fExpandCollapseButton.setEnabled(b);
	}

}
