/*******************************************************************************
 * Copyright (c) 2017, 2020 GK Software SE, 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:
 *     Stephan Herrmann - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.wizards.buildpaths;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.core.runtime.IStatus;

import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.util.BidiUtils;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;

import org.eclipse.ui.PlatformUI;

import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.JavaElementLabels;

import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaPrecomputedNamesAssistProcessor;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.LimitModules;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddExport;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddExpose;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddReads;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModulePatch;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;

public class ModuleDialog extends StatusDialog {

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

	static class ListContentProvider implements IStructuredContentProvider {
		List<?> fContents;

		@Override
		public Object[] getElements(Object input) {
			if (fContents != null && fContents == input)
				return fContents.toArray();
			return new Object[0];
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			if (newInput instanceof List<?>)
				fContents= (List<?>)newInput;
			else
				fContents= null;
		}
	}

	static class ModulesLabelProvider extends LabelProvider implements ITableLabelProvider {

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE);
		}

		@Override
		public String getColumnText(Object element, int columnIndex) {
			return element.toString();
		}

	}

	public static class AddDetailsLabelProvider extends LabelProvider implements ITableLabelProvider {

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int columnIndex) {
			if (element instanceof ModuleAddExport) {
				ModuleAddExport export= (ModuleAddExport) element;
				switch (columnIndex) {
					case 0: return export.fSourceModule;
					case 1: return export.fPackage;
					case 2: return export.fTargetModules;
					default:
						throw new IllegalArgumentException("Illegal column index "+columnIndex); //$NON-NLS-1$
				}
			} else if (element instanceof ModuleAddReads) {
				ModuleAddReads reads= (ModuleAddReads) element;
				switch (columnIndex) {
					case 0: return reads.fSourceModule;
					case 1: return reads.fTargetModule;
					default:
						throw new IllegalArgumentException("Illegal column index "+columnIndex); //$NON-NLS-1$
				}
			}
			return NO_NAME;
		}

	}

	private final SelectionButtonDialogField fIsModuleCheckbox;

	static class ModuleList {
		TableViewer fViewer;
		List<String> fNames;
		public ModuleList(List<String> names) {
			fNames= names;
		}
	}
	private ModuleList[] fModuleLists= new ModuleList[3];
	private static final int IDX_AVAILABLE= 0;
	private static final int IDX_INCLUDED= 1;
	private static final int IDX_IMPLICITLY_INCLUDED= 2;

	private BuildPathBasePage fBasePage;

	private Button fAddIncludedButton;
	private Button fRemoveIncludedButton;
	private Button fPromoteIncludedButton;

	private final SelectionButtonDialogField fIsPatchCheckbox;
	private final StringDialogField fPatchedModule;

	private final ListDialogField<ModuleAddExpose> fAddExportsList;

	private final ListDialogField<ModuleAddReads> fAddReadsList;

	private final CPListElement fCurrCPElement;
	/** The element(s) targeted by the current CP entry, which will be the source module(s) of the added exports. */
	private IJavaElement[] fJavaElements;
	private Set<String> fModuleNames;

	private Map<String,List<String>> fModule2RequiredModules;

	private static final int IDX_ADD= 0;
	private static final int IDX_EDIT= 1;
	private static final int IDX_REMOVE= 2;


	public ModuleDialog(Shell parent, CPListElement entryToEdit, IJavaElement[] selectedElements, BuildPathBasePage basePage) {
		super(parent);

		fBasePage= basePage;
		fCurrCPElement= entryToEdit;
		fJavaElements= selectedElements;

		setTitle(NewWizardMessages.ModuleDialog_title);

		fIsModuleCheckbox= new SelectionButtonDialogField(SWT.CHECK);
		fIsModuleCheckbox.setLabelText(NewWizardMessages.ModuleDialog_defines_modules_label);
		fIsModuleCheckbox.setSelection(entryToEdit.getAttribute(CPListElement.MODULE) != null);
		fIsModuleCheckbox.setDialogFieldListener(field -> doSelectionChangedAllLists());

		// -- contents page initialized in createContentsTab()

		// -- details page:

		fIsPatchCheckbox= new SelectionButtonDialogField(SWT.CHECK);
		fIsPatchCheckbox.setLabelText(NewWizardMessages.ModuleDialog_patches_module_label);
		fIsPatchCheckbox.setDialogFieldListener(this::doPatchSelectionChanged);

		fPatchedModule= new StringDialogField();
		fPatchedModule.setLabelText(NewWizardMessages.ModuleDialog_patched_module_label);
		fPatchedModule.setDialogFieldListener(this::validateDetails);

		fAddExportsList= createDetailListContents(entryToEdit, NewWizardMessages.ModuleDialog_exports_label, new AddExportsAdapter(), ModuleAddExpose.class);
		fAddReadsList= createDetailListContents(entryToEdit, NewWizardMessages.ModuleDialog_reads_label, new AddReadsAdapter(), ModuleAddReads.class);

		initializeValues();

		doPatchSelectionChanged(fIsPatchCheckbox);
		doSelectionChangedAllLists();
	}

	@Override
	protected boolean isResizable() {
		return true;
	}

	private <T extends ModuleEncapsulationDetail> ListDialogField<T> createDetailListContents(CPListElement entryToEdit, String label, ListAdapter<T> adapter, Class<T> clazz) {
		String[] buttonLabels= new String[] {
				NewWizardMessages.ModuleDialog_detail_add,
				NewWizardMessages.ModuleDialog_detail_edit,
				NewWizardMessages.ModuleDialog_detail_remove
		};

		AddDetailsLabelProvider labelProvider= new AddDetailsLabelProvider();

		ListDialogField<T> detailsList= new ListDialogField<>(adapter, buttonLabels, labelProvider);

		detailsList.setLabelText(label);
		detailsList.setRemoveButtonIndex(IDX_REMOVE);
		detailsList.enableButton(IDX_EDIT, false);

		detailsList.setElements(entryToEdit.getModuleEncapsulationDetails(clazz));
		detailsList.selectFirstElement();
		return detailsList;
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		Composite composite= (Composite) super.createDialogArea(parent);
		GridLayout layout= new GridLayout(1, true);
		layout.marginBottom= 0;
		composite.setLayout(layout);

		Label description= new Label(composite, SWT.WRAP);

		description.setText(getDescriptionString());

		GridData data= new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1);
		data.widthHint= convertWidthInCharsToPixels(100);
		description.setLayoutData(data);

		fIsModuleCheckbox.doFillIntoGrid(composite, 3);


		TabFolder tabFolder= new TabFolder(composite, SWT.NONE);
		tabFolder.setFont(composite.getFont());
		tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		final TabItem tabItemContents= new TabItem(tabFolder, SWT.NONE);
		tabItemContents.setText(NewWizardMessages.ModuleDialog_contents_tab);
		tabItemContents.setImage(JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE));
		tabItemContents.setControl(createContentsTab(tabFolder));

		final TabItem tabItemDetails= new TabItem(tabFolder, SWT.NONE);
		tabItemDetails.setText(NewWizardMessages.ModuleDialog_details_tab);
		tabItemDetails.setImage(JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE_ATTRIB));
		tabItemDetails.setControl(createDetailsTab(tabFolder));

		tabFolder.addSelectionListener(widgetSelectedAdapter(e -> validateTab(e.widget, tabItemContents, tabItemDetails)));

		applyDialogFont(composite);
		updateStatus(new StatusInfo(IStatus.WARNING, NewWizardMessages.ModuleDialog_deprecated_warning));
		return composite;
	}

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		if (fBasePage.fSWTControl != null) {
			Button switchButton= createButton(parent, 2, NewWizardMessages.ModuleDialog_switchToTab_button, false);
			switchButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
				fBasePage.switchToTab(ModuleDependenciesPage.class);
				cancelPressed();
			}));
		}
		super.createButtonsForButtonBar(parent);
	}

	private String getDescriptionString() {
		String desc;
		String name= BasicElementLabels.getResourceName(fCurrCPElement.getPath().lastSegment());
		switch (fCurrCPElement.getEntryKind()) {
			case IClasspathEntry.CPE_CONTAINER:
				try {
					name= JavaElementLabels.getContainerEntryLabel(fCurrCPElement.getPath(), fCurrCPElement.getJavaProject());
				} catch (JavaModelException e) {
					name= BasicElementLabels.getPathLabel(fCurrCPElement.getPath(), false);
				}
				desc= NewWizardMessages.ModuleDialog_container_description;
				break;
			case IClasspathEntry.CPE_PROJECT:
				desc=  NewWizardMessages.ModuleDialog_project_description;
				break;
			default:
				desc=  NewWizardMessages.ModuleDialog_description;
		}

		return Messages.format(desc, name);
	}

	Composite createContentsTab(Composite parent) {
		Composite contentsPage= new Composite(parent, SWT.NONE);
		contentsPage.setFont(parent.getFont());
		applyDialogFont(contentsPage);

		GridLayout layout= new GridLayout();
		layout.marginTop= 5;
		layout.marginHeight= 0;
		layout.marginWidth= 0;
		layout.numColumns= 3; // list , buttons , list
		contentsPage.setLayout(layout);
		contentsPage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		// top
		createContentListContents(contentsPage,
				NewWizardMessages.ModuleDialog_availableModules_list,
				NewWizardMessages.ModuleDialog_availableModules_tooltip,
				IDX_AVAILABLE, IDX_INCLUDED);
		createHorizontalButtons(contentsPage);
		createContentListContents(contentsPage,
				NewWizardMessages.ModuleDialog_explicitlyIncludedModules_list,
				NewWizardMessages.ModuleDialog_explicitlyIncludedModules_tooltip,
				IDX_INCLUDED, IDX_AVAILABLE);

		// bottom
		Label spacer= new Label(contentsPage, SWT.NONE);
		GridData gd= new GridData();
		gd.horizontalSpan= 2;
		spacer.setLayoutData(gd);

		Composite lowerRight= new Composite(contentsPage, SWT.NONE);
		lowerRight.setLayout(new GridLayout(1, true));
		gd= new GridData(SWT.FILL, SWT.FILL, true, true);
		lowerRight.setLayoutData(gd);

		createVerticalButton(lowerRight);
		createContentListContents(lowerRight,
				NewWizardMessages.ModuleDialog_implicitelyIncludedModules_list,
				NewWizardMessages.ModuleDialog_implicitlyIncludedModule_tooltip,
				IDX_IMPLICITLY_INCLUDED, IDX_INCLUDED);

		validateContents();

		return contentsPage;
	}

	Composite createDetailsTab(Composite parent) {
		Composite detailPage= new Composite(parent, SWT.NONE);
		detailPage.setFont(parent.getFont());
		applyDialogFont(detailPage);

		GridLayout layout= new GridLayout();
		layout.marginTop= 5;
		layout.marginHeight= 0;
		layout.marginWidth= 0;
		layout.numColumns= 3;
		detailPage.setLayout(layout);
		detailPage.setLayoutData(new GridData(GridData.FILL_BOTH));

		fIsPatchCheckbox.doFillIntoGrid(detailPage, 3);
		fPatchedModule.doFillIntoGrid(detailPage, 2);
		GridData data= (GridData) fPatchedModule.getLabelControl(null).getLayoutData();
		data.horizontalIndent= LayoutUtil.getIndent();

		Text patchedModuleText= fPatchedModule.getTextControl(null);
		BidiUtils.applyBidiProcessing(patchedModuleText, StructuredTextTypeHandlerFactory.JAVA);
		if (fJavaElements != null) {
			configureModuleContentAssist(patchedModuleText, moduleNames());
		}

		ColumnLayoutData[] columnDta= {
				new ColumnWeightData(2),
				new ColumnWeightData(3),
				new ColumnWeightData(2),
		};
		String[] headers= {
				NewWizardMessages.ModuleDialog_source_module_header,
				NewWizardMessages.ModuleDialog_package_header,
				NewWizardMessages.ModuleDialog_target_module_header
		};
		fAddExportsList.setTableColumns(new ListDialogField.ColumnsDescription(columnDta, headers, true));

		fAddExportsList.doFillIntoGrid(detailPage, 4);

		LayoutUtil.setHorizontalSpan(fAddExportsList.getLabelControl(null), 3);

		data= (GridData) fAddExportsList.getListControl(null).getLayoutData();
		data.grabExcessHorizontalSpace= true;
		data.heightHint= SWT.DEFAULT;

		columnDta= new ColumnWeightData[] {
				new ColumnWeightData(1),
				new ColumnWeightData(1),
		};
		headers= new String[] {
				NewWizardMessages.ModuleDialog_source_module_header,
				NewWizardMessages.ModuleDialog_target_module_header
		};
		fAddReadsList.setTableColumns(new ListDialogField.ColumnsDescription(columnDta, headers, true));

		fAddReadsList.doFillIntoGrid(detailPage, 4);

		LayoutUtil.setHorizontalSpan(fAddReadsList.getLabelControl(null), 3);

		data= (GridData) fAddReadsList.getListControl(null).getLayoutData();
		data.grabExcessHorizontalSpace= true;
		data.heightHint= SWT.DEFAULT;
		return detailPage;
	}

	// ======== widgets for the Contents tab: ========

	private void createContentListContents(Composite parent, String title, String tooltip, int idx, int targetIdx) {
		Composite box= new Composite(parent, SWT.NONE);
		GridLayout layout= new GridLayout(1, false);
		layout.marginBottom= 0;
		box.setLayout(layout);
		GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
		gd.minimumWidth= 0;
		box.setLayoutData(gd);

		Label label= new Label(box, SWT.NONE);
		label.setText(title);
		label.setToolTipText(tooltip);

		TableViewer tableViewer= new TableViewer(box, SWT.MULTI | SWT.BORDER);
		tableViewer.setContentProvider(new ListContentProvider());
		tableViewer.setLabelProvider(new ModulesLabelProvider());
		tableViewer.addDoubleClickListener(e -> moveModuleEntry(idx, targetIdx));
		tableViewer.setInput(fModuleLists[idx].fNames);
		tableViewer.addSelectionChangedListener(e -> validateContents());
		tableViewer.setComparator(new ViewerComparator() {
			@Override
			public int compare(Viewer viewer, Object e1, Object e2) {
				return ((String)e1).compareTo((String)e2);
			}
		});

		PixelConverter converter= new PixelConverter(parent);
		gd= new GridData(SWT.FILL, SWT.FILL, true, true);
		gd.widthHint= converter.convertWidthInCharsToPixels(30);
		gd.heightHint= converter.convertHeightInCharsToPixels(6);
		tableViewer.getControl().setLayoutData(gd);

		fModuleLists[idx].fViewer= tableViewer;
	}

	private void createHorizontalButtons(Composite parent) {
		org.eclipse.ui.ISharedImages sharedImages= PlatformUI.getWorkbench().getSharedImages();

		Composite box= new Composite(parent, SWT.NONE);
		box.setLayout(new GridLayout(1, true));

		fAddIncludedButton= new Button(box, SWT.PUSH);
		fAddIncludedButton.setImage(sharedImages.getImage(org.eclipse.ui.ISharedImages.IMG_TOOL_FORWARD));
		fAddIncludedButton.setToolTipText(NewWizardMessages.ModuleDialog_addToIncluded_tooltip);
		fAddIncludedButton.addSelectionListener(widgetSelectedAdapter(e -> moveModuleEntry(IDX_AVAILABLE, IDX_INCLUDED)));

		fRemoveIncludedButton= new Button(box, SWT.PUSH);
		fRemoveIncludedButton.setImage(sharedImages.getImage(org.eclipse.ui.ISharedImages.IMG_TOOL_BACK));
		fRemoveIncludedButton.setToolTipText(NewWizardMessages.ModuleDialog_removeFromIncluded_tooltip);
		fRemoveIncludedButton.addSelectionListener(widgetSelectedAdapter(e -> moveModuleEntry(IDX_INCLUDED, IDX_AVAILABLE)));
	}

	private void createVerticalButton(Composite parent) {
		fPromoteIncludedButton= new Button(parent, SWT.PUSH);
		fPromoteIncludedButton.setImage(JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_BUTTON_MOVE_UP));
		fPromoteIncludedButton.setToolTipText(NewWizardMessages.ModuleDialog_addToExplicitlyIncluded_tooltip);
		fPromoteIncludedButton.addSelectionListener(widgetSelectedAdapter(e -> moveModuleEntry(IDX_IMPLICITLY_INCLUDED, IDX_INCLUDED)));
		GridData gd= new GridData();
		gd.horizontalAlignment= SWT.CENTER;
		fPromoteIncludedButton.setLayoutData(gd);
	}

	private boolean canRemoveIncludedModules() {
		if (fModuleLists[IDX_INCLUDED].fViewer.getSelection().isEmpty())
			return false;
		return fModuleLists[IDX_INCLUDED].fNames.size() + fModuleLists[IDX_AVAILABLE].fNames.size() > 1;
	}

	private void moveModuleEntry(int sourceIdx, int targetIdx) {
		ISelection selection= fModuleLists[sourceIdx].fViewer.getSelection();
		if (selection instanceof IStructuredSelection) {
			if (sourceIdx == IDX_INCLUDED && !canRemoveIncludedModules()) {
				return;
			}
			List<String> sourceList= fModuleLists[sourceIdx].fNames;
			List<String> targetList= fModuleLists[targetIdx].fNames;
			for (Object selected : ((IStructuredSelection) selection)) {
				if (selected instanceof String) {
					sourceList.remove(selected);
					targetList.add((String) selected);
				}
			}
			updateImplicitlyIncluded();
			fModuleLists[IDX_AVAILABLE].fViewer.refresh();
			fModuleLists[IDX_INCLUDED].fViewer.refresh();
			fModuleLists[IDX_IMPLICITLY_INCLUDED].fViewer.refresh();
			validateContents();
		}
	}

	public static void configureModuleContentAssist(Text textControl, Collection<String> moduleNames) {
		if (moduleNames.size() == 1) {
			textControl.setText(moduleNames.iterator().next());
		} else if (!moduleNames.isEmpty()) {
			Image image= JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE);
			JavaPrecomputedNamesAssistProcessor processor= new JavaPrecomputedNamesAssistProcessor(moduleNames, image);
			ControlContentAssistHelper.createTextContentAssistant(textControl, processor);
		}
	}

	// ======== updating & validation: ========

	protected void doPatchSelectionChanged(DialogField field) {
		fPatchedModule.setEnabled(fIsPatchCheckbox.isSelected() && moduleNames().size() != 1);
		validateDetails(field);
	}

	protected void doSelectionChangedAllLists() {
		doSelectionChanged(fAddExportsList);
		doSelectionChanged(fAddReadsList);
	}

	protected void doSelectionChanged(ListDialogField<? extends ModuleEncapsulationDetail> field) {
		boolean isModular= fIsModuleCheckbox.isSelected();
		List<? extends ModuleEncapsulationDetail> selected= field.getSelectedElements();
		field.enableButton(IDX_ADD, isModular && fJavaElements != null);
		field.enableButton(IDX_EDIT, isModular && canEdit(selected));
		field.enableButton(IDX_REMOVE, isModular && selected.size() > 0);
		validateDetails(field);
	}

	private boolean canEdit(List<? extends ModuleEncapsulationDetail> selected) {
		return selected.size() == 1;
	}

	private void validateTab(Widget widget, Widget contentItem, Widget detailsItem) {
		if (widget instanceof TabFolder) {
			TabItem[] selected= ((TabFolder) widget).getSelection();
			for (TabItem selectedItem : selected) {
				if (selectedItem == contentItem) {
					validateContents();
					return;
				} else if (selectedItem == detailsItem) {
					validateDetails(null);
					return;
				}
			}
		}
	}

	private void validateContents() {
		fAddIncludedButton.setEnabled(!fModuleLists[IDX_AVAILABLE].fViewer.getSelection().isEmpty());
		fRemoveIncludedButton.setEnabled(canRemoveIncludedModules());
		fPromoteIncludedButton.setEnabled(!fModuleLists[IDX_IMPLICITLY_INCLUDED].fViewer.getSelection().isEmpty());
		IStatus status= computeContentsStatus();
		updateStatus(status);
		if (status.isOK()) {
			status= computeDetailsStatus(null);
			if (status.getSeverity() == IStatus.ERROR) {
				updateStatus(new StatusInfo(IStatus.ERROR, NewWizardMessages.ModuleDialog_errorOnDetailsTab_error));
			}
		}
	}

	private IStatus computeContentsStatus() {
		StatusInfo info= new StatusInfo();
		if (fIsModuleCheckbox.isSelected()) {
			if (fJavaElements != null) {
				if (fModuleLists[IDX_INCLUDED].fNames.isEmpty()) {
					info.setError(NewWizardMessages.ModuleDialog_mustIncludeModule_error);
				} else if (fModuleLists[IDX_INCLUDED].fNames.size() + fModuleLists[IDX_AVAILABLE].fNames.size() == 1) {
					info.setInfo(NewWizardMessages.ModuleDialog_cannotLimitSingle_error);
				}
			} else {
				info.setInfo(NewWizardMessages.ModuleDialog_unknownModules_info);
			}
		}
		return info;
	}

	private void validateDetails(DialogField field) {
		IStatus status= computeDetailsStatus(field);
		updateStatus(status);
		if (status.isOK()) {
			status= computeContentsStatus();
			if (status.getSeverity() == IStatus.ERROR) {
				updateStatus(new StatusInfo(IStatus.ERROR, NewWizardMessages.ModuleDialog_errorOnContentsTab_error));
			}
		}
	}

	private StatusInfo computeDetailsStatus(DialogField field) {
		Set<String> packages= new HashSet<>();
		StatusInfo status= new StatusInfo();
		if (fIsPatchCheckbox.isSelected()) {
			String patchedModule= fPatchedModule.getText().trim();
			if (patchedModule.isEmpty()) {
				if (field == fIsPatchCheckbox) {
					status= newSilentError(); // silently disable OK button until user input is given
				} else {
					status.setError(NewWizardMessages.ModuleDialog_missingPatch_error);
				}
				Shell shell= getShell();
				if (shell != null) {
					fPatchedModule.getTextControl(shell).setFocus();
				}
			} else if (!moduleNames().isEmpty() && !moduleNames().contains(patchedModule)) {
				status.setError(Messages.format(NewWizardMessages.ModuleDialog_wrongPatch_error, patchedModule));
			} else if (isModuleExcluded(patchedModule)) {
				status.setError(Messages.format(NewWizardMessages.ModuleDialog_patchedModuleExcluded_error, patchedModule));
			}
		}
		if (status.isOK()) {
			for (ModuleAddExpose export : fAddExportsList.getElements()) {
				if (!packages.add(export.fPackage)) {
					status.setError(Messages.format(NewWizardMessages.ModuleDialog_duplicatePackage_error, export.fPackage));
					break;
				}
				if (isModuleExcluded(export.fSourceModule)) {
					status.setError(Messages.format(NewWizardMessages.ModuleDialog_exportSourceModuleExcluded_error,
							new String[]{ export.fPackage, export.fSourceModule }));
				}
			}
		}
		if (status.isOK()) {
			Set<String> readModules= new HashSet<>();
			for (ModuleAddReads reads : fAddReadsList.getElements()) {
				if (!readModules.add(reads.toString())) {
					status.setError(Messages.format(NewWizardMessages.ModuleDialog_duplicateReads_error, reads.toString()));
					break;
				}
				if (isModuleExcluded(reads.fSourceModule)) {
					status.setError(Messages.format(NewWizardMessages.ModuleDialog_readsSourceModuleExcluded_error,
							reads.fSourceModule));
				}
			}
		}
		if (status.isOK() && fJavaElements == null) {
			status.setInfo(NewWizardMessages.ModuleDialog_cannotEditDetails_info);
		}
		return status;
	}

	private boolean isModuleExcluded(String moduleName) {
		return fModuleLists[IDX_AVAILABLE].fNames.contains(moduleName);
	}

	// ======== operations on values, i.e., classpath entries, modules and packages: ========

	private void initializeValues() {
		fModule2RequiredModules= new HashMap<>();

		boolean isJava9JRE= isJava9JRE();
		List<String> availableNames= new ArrayList<>(moduleNames());
		List<String> includedNames= new ArrayList<>();
		List<LimitModules> limits= fCurrCPElement.getModuleEncapsulationDetails(LimitModules.class);
		if (!limits.isEmpty()) {
			for (LimitModules limitModules : limits) {
				includedNames.addAll(limitModules.fExplicitlyIncludedModules);
				availableNames.removeAll(limitModules.fExplicitlyIncludedModules);
			}
		} else if (isJava9JRE && isUnnamedModule()) {
			includedNames= defaultIncludedModuleNamesForUnnamedModule();
			availableNames.removeAll(includedNames);
		} else {
			includedNames= availableNames;
			availableNames= new ArrayList<>();
		}
		fModuleLists[IDX_AVAILABLE]= new ModuleList(availableNames);
		fModuleLists[IDX_INCLUDED]= new ModuleList(new ArrayList<>(includedNames));
		fModuleLists[IDX_IMPLICITLY_INCLUDED]= new ModuleList(new ArrayList<>());
		updateImplicitlyIncluded();

		// access to widgets may trigger validation, which needs all values to be initialized (non-null):

		if (isJava9JRE) {
			fIsModuleCheckbox.setEnabled(false);
		}

		List<ModulePatch> patchedModules= fCurrCPElement.getModuleEncapsulationDetails(ModulePatch.class);
		fIsPatchCheckbox.setSelection(!patchedModules.isEmpty());

		if (patchedModules.size() == 1)
			fPatchedModule.setText(patchedModules.iterator().next().fModule);
	}

	private boolean isJava9JRE() {
		if (fCurrCPElement.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
			IPackageFragmentRoot[] roots= findRoots(fCurrCPElement);
			if (roots.length > 1 && roots[0].getModuleDescription() != null)
				return true; // assume multi-module container is Java 9 JRE
		}
		return false;
	}
	private IPackageFragmentRoot[] findRoots(CPListElement element) {
		IClasspathEntry entry= element.getClasspathEntry();
		IPackageFragmentRoot[] roots= element.getJavaProject().findPackageFragmentRoots(entry);
		if (roots.length == 0) {
			// 2nd attempt in case "module=true" is not explicit on the real cp entry:
			entry= copyCPEntryWithoutModuleAttribute(entry);
			if (entry != null)
				roots= element.getJavaProject().findPackageFragmentRoots(entry);
		}
		return roots;
	}

	private IClasspathEntry copyCPEntryWithoutModuleAttribute(IClasspathEntry entry) {
		IClasspathAttribute[] oldAttributes= entry.getExtraAttributes();
		IClasspathAttribute[] newAttributes= new IClasspathAttribute[oldAttributes.length];
		int count= 0;
		for (IClasspathAttribute oldAttribute : oldAttributes) {
			if (!oldAttribute.getName().equals(IClasspathAttribute.MODULE)) {
				newAttributes[count++]= oldAttribute;
			}
		}
		if (count == oldAttributes.length)
			return null;
		newAttributes= count == 0 ? new IClasspathAttribute[0] : Arrays.copyOf(newAttributes, count);
		return JavaCore.newContainerEntry(entry.getPath(), entry.getAccessRules(), newAttributes, entry.isExported());
	}

	private Set<String> moduleNames() {
		if (fModuleNames != null)
			return fModuleNames;
		Set<String> moduleNames= new HashSet<>();
		if (fJavaElements != null) {
			for (IJavaElement element : fJavaElements) {
				if (element instanceof IPackageFragmentRoot) {
					IModuleDescription module= ((IPackageFragmentRoot) element).getModuleDescription();
					if (module != null) {
						recordModule(module, moduleNames);
					} else {
						try {
							recordModule(JavaCore.getAutomaticModuleDescription(element), moduleNames);
						}catch (JavaModelException e) {
							JavaPlugin.log(e);
						}
					}
				} else if (element instanceof IJavaProject) {
					try {
						IModuleDescription module= ((IJavaProject) element).getModuleDescription();
						if (module != null) {
							recordModule(module, moduleNames);
						} else {
							recordModule(JavaCore.getAutomaticModuleDescription(element), moduleNames);
						}
					} catch (JavaModelException e) {
						JavaPlugin.log(e);
					}
				}
			}
		}
		return fModuleNames= moduleNames;
	}

	private List<String> defaultIncludedModuleNamesForUnnamedModule() {
		if (fJavaElements != null) {
			List<IPackageFragmentRoot> roots= new ArrayList<>();
			for (IJavaElement element : fJavaElements) {
				if (element instanceof IPackageFragmentRoot) {
					roots.add((IPackageFragmentRoot) element);
				}
			}
			return JavaCore.defaultRootModules(roots);
		}
		return Collections.emptyList();
	}

	private void recordModule(IModuleDescription module, Set<String> moduleNames) {
		String moduleName= module.getElementName();
		if (moduleNames.add(moduleName)) {
			try {
				for (String required : module.getRequiredModuleNames()) {
					List<String> requiredModules= fModule2RequiredModules.get(moduleName);
					if (requiredModules == null) {
						requiredModules= new ArrayList<>();
						fModule2RequiredModules.put(moduleName, requiredModules);
					}
					requiredModules.add(required);
				}
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
	}

	private void updateImplicitlyIncluded() {
		List<String> implicitNames= fModuleLists[IDX_IMPLICITLY_INCLUDED].fNames;
		fModuleLists[IDX_AVAILABLE].fNames.addAll(implicitNames);
		implicitNames.clear();
		for (String explicitName : fModuleLists[IDX_INCLUDED].fNames) {
			if (!implicitNames.contains(explicitName)) {
				collectRequired(explicitName);
			}
		}
	}

	private void collectRequired(String explicitName) {
		List<String> requireds= fModule2RequiredModules.get(explicitName);
		if (requireds == null) {
			return;
		}
		List<String> implicitNames= fModuleLists[IDX_IMPLICITLY_INCLUDED].fNames;
		for (String required : requireds) {
			if (!fModuleLists[IDX_INCLUDED].fNames.contains(required)) {
				if (!implicitNames.contains(required)) {
					if (fModuleLists[IDX_AVAILABLE].fNames.remove(required)) {
						implicitNames.add(required);
						collectRequired(required);
					}
				}
			}
		}
	}

	private String getSourceModuleName() {
		if (fJavaElements == null || fJavaElements.length != 1) {
			return NO_NAME;
		}
		IModuleDescription module= null;
		switch (fJavaElements[0].getElementType()) {
			case IJavaElement.JAVA_PROJECT:
				try {
					module= ((IJavaProject) fJavaElements[0]).getModuleDescription();
				} catch (JavaModelException e) {
					JavaPlugin.log(e);
				}
				break;
			case IJavaElement.PACKAGE_FRAGMENT_ROOT:
				module= ((IPackageFragmentRoot) fJavaElements[0]).getModuleDescription();
				break;
			default:
				// not applicable
		}
		return module != null ? module.getElementName() : NO_NAME;
	}

	private String getCurrentModuleName() {
		IModuleDescription module= null;
		try {
			module= fCurrCPElement.getJavaProject().getModuleDescription();
		} catch (JavaModelException e) {
			JavaPlugin.log(e);
		}
		return module != null ? module.getElementName() : JavaModelUtil.ALL_UNNAMED;
	}

	private boolean isUnnamedModule() {
		IModuleDescription module= null;
		try {
			module= fCurrCPElement.getJavaProject().getModuleDescription();
		} catch (JavaModelException e) {
			JavaPlugin.log(e);
		}
		return module == null;
	}

	// -------- TypeRestrictionAdapter --------

	private abstract class ListAdapter<T extends ModuleEncapsulationDetail> implements IListAdapter<T> {
		/**
		 * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#customButtonPressed(org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField, int)
		 */
		@Override
		public void customButtonPressed(ListDialogField<T> field, int index) {
			if (index == IDX_ADD) {
				addEntry(field);
			} else if (index == IDX_EDIT) {
				doubleClicked(field);
			}
		}

		/**
		 * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#selectionChanged(org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField)
		 */
		@Override
		public void selectionChanged(ListDialogField<T> field) {
			doSelectionChanged(field);
		}
		/**
		 * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#doubleClicked(org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField)
		 */
		@Override
		public void doubleClicked(ListDialogField<T> field) {
			List<T> selElements= field.getSelectedElements();
			if (selElements.size() != 1) {
				return;
			}
			editEntry(field, selElements.get(0));
		}

		abstract void addEntry(ListDialogField<T> field);

		abstract void editEntry(ListDialogField<T> field, T detail);
	}

	private class AddExportsAdapter extends ListAdapter<ModuleAddExpose> {

		@Override
		void addEntry(ListDialogField<ModuleAddExpose> field) {
			ModuleAddExport initialValue= new ModuleAddExport(getSourceModuleName(), NO_NAME, getCurrentModuleName(), null);
			ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(getShell(), fJavaElements, null, initialValue, null);
			if (dialog.open() == Window.OK) {
				ModuleAddExpose export= dialog.getExport(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
				if (export != null)
					field.addElement(export);
			}
		}

		@Override
		void editEntry(ListDialogField<ModuleAddExpose> field, ModuleAddExpose export) {
			ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(getShell(), fJavaElements, null, export, null);
			if (dialog.open() == Window.OK) {
				ModuleAddExpose newExport= dialog.getExport(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
				if (newExport != null) {
					field.replaceElement(export, newExport);
				} else {
					field.removeElement(export);
				}
			}
		}
	}

	private class AddReadsAdapter extends ListAdapter<ModuleAddReads> {

		@Override
		void addEntry(ListDialogField<ModuleAddReads> field) {
			ModuleAddReads initialValue= new ModuleAddReads(getSourceModuleName(), NO_NAME, null);
			ModuleAddReadsDialog dialog= new ModuleAddReadsDialog(getShell(), fJavaElements, initialValue);
			if (dialog.open() == Window.OK) {
				ModuleAddReads reads= dialog.getReads(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
				if (reads != null)
					field.addElement(reads);
			}
		}

		@Override
		void editEntry(ListDialogField<ModuleAddReads> field, ModuleAddReads reads) {
			ModuleAddReadsDialog dialog= new ModuleAddReadsDialog(getShell(), fJavaElements, reads);
			if (dialog.open() == Window.OK) {
				ModuleAddReads newReads= dialog.getReads(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
				if (newReads != null) {
					field.replaceElement(reads, newReads);
				} else {
					field.removeElement(reads);
				}
			}
		}
	}

	/**
	 * When the dialog is closed, this method provides the results.
	 * @return an array of ModuleEncapsulationDetail encoding the result of editing
	 */
	public ModuleEncapsulationDetail[] getAllDetails() {
		if (!fIsModuleCheckbox.isSelected())
			return null;
		CPListElementAttribute attribute= fCurrCPElement.findAttributeElement(CPListElement.MODULE);
		List<ModuleEncapsulationDetail> allElements= new ArrayList<>();
		allElements.addAll(fAddExportsList.getElements());
		allElements.addAll(fAddReadsList.getElements());
		if (fIsPatchCheckbox.isSelected()) {
			String patchedModule= fPatchedModule.getText().trim();
			if (!patchedModule.isEmpty())
				allElements.add(ModulePatch.fromString(attribute, patchedModule));
		}
		if (modifiesContents()) {
			allElements.add(new ModuleEncapsulationDetail.LimitModules(fModuleLists[IDX_INCLUDED].fNames, attribute));
		}
		return allElements.toArray(new ModuleEncapsulationDetail[allElements.size()]);
	}

	private boolean modifiesContents() {
		if (fModuleLists[IDX_AVAILABLE].fNames.isEmpty() && fModuleLists[IDX_IMPLICITLY_INCLUDED].fNames.isEmpty()) {
			return false; // all modules are "included" - this includes the single-module case.
		}
		if (isUnnamedModule()) {
			// for an unnamed module we need to compare current selection state against defaults per JEP 261:
			Set<String> initialNames = new HashSet<>(defaultIncludedModuleNamesForUnnamedModule());
			for (String name : fModuleLists[IDX_INCLUDED].fNames) {
				if (!initialNames.remove(name))
					return true;
			}
			return !initialNames.isEmpty();
		} else {
			return true;
		}
	}

	/*
	 * @see org.eclipse.jface.window.Window#configureShell(Shell)
	 */
	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IJavaHelpContextIds.MODULE_DIALOG);
	}

	public static StatusInfo newSilentError() {
		return new StatusInfo(IStatus.ERROR, Util.ZERO_LENGTH_STRING);
	}
}
