/*******************************************************************************
 * Copyright (c) 2007, 2011 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
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.fix;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;

import com.ibm.icu.text.Collator;

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.Text;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;

import org.eclipse.jface.util.SafeRunnable;

import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
import org.eclipse.jdt.ui.cleanup.ICleanUp;
import org.eclipse.jdt.ui.cleanup.ICleanUpConfigurationUI;
import org.eclipse.jdt.ui.cleanup.ICleanUpOptionsInitializer;

import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.fix.MapCleanUpOptions;
import org.eclipse.jdt.internal.ui.preferences.cleanup.CleanUpTabPage;
import org.eclipse.jdt.internal.ui.preferences.cleanup.ContributedCleanUpTabPage;
import org.eclipse.jdt.internal.ui.util.SWTUtil;

/**
 * The clean up registry provides a set of clean ups and there corresponding UI representatives.
 *
 * @since 3.4
 */
public class CleanUpRegistry {

	private static final class ErrorPage implements ICleanUpConfigurationUI {

		private final Exception fException;

		private ErrorPage(Exception e) {
			fException= e;
		}

		@Override
		public Composite createContents(Composite parent) {
			Composite result= new Composite(parent, SWT.NONE);
			result.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
			result.setLayout(new GridLayout(1, false));

			Text text= new Text(result, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY);
			SWTUtil.fixReadonlyTextBackground(text);
			text.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
			text.setText(Messages.format(FixMessages.CleanUpRegistry_ErrorTabPage_description, fException.getLocalizedMessage()));

			return result;
		}

		@Override
		public int getCleanUpCount() {
			return 0;
		}

		@Override
		public String getPreview() {
			return FixMessages.CleanUpRegistry_ErrorTabPage_preview;
		}

		@Override
		public int getSelectedCleanUpCount() {
			return 0;
		}

		@Override
		public void setOptions(CleanUpOptions options) {
		}
	}

	public static class CleanUpTabPageDescriptor {

		private static final String ATTRIBUTE_ID_CLASS= "class"; //$NON-NLS-1$
		private static final String ATTRIBUTE_ID_NAME= "name"; //$NON-NLS-1$
		private static final String ATTRIBUTE_NAME_KIND= "cleanUpKind"; //$NON-NLS-1$

		private final String fName;
		private final IConfigurationElement fElement;
		private int fKind;

		/**
		 * @param element the configuration element
		 */
		public CleanUpTabPageDescriptor(IConfigurationElement element) {
			fElement= element;
			fName= element.getAttribute(ATTRIBUTE_ID_NAME);
			String kind= fElement.getAttribute(ATTRIBUTE_NAME_KIND);
			fKind= getCleanUpKind(kind);
			if (fKind == -1)
				JavaPlugin.logErrorMessage(Messages.format(FixMessages.CleanUpRegistry_WrongKindForConfigurationUI_error, new String[] { fName, element.getContributor().getName(),
						kind }));
		}

		/**
		 * @return the name of the tab
		 */
		public String getName() {
			return fName;
		}

		/**
		 * @return the kind of clean up
		 */
		public int getKind() {
			return fKind;
		}

		/**
		 * @return new instance of a tab page
		 */
		public CleanUpTabPage createTabPage() {
			try {
				ICleanUpConfigurationUI page= (ICleanUpConfigurationUI)fElement.createExecutableExtension(ATTRIBUTE_ID_CLASS);
				if (page instanceof CleanUpTabPage)
					return (CleanUpTabPage)page;

				return new ContributedCleanUpTabPage(page);
			} catch (final CoreException e) {
				JavaPlugin.log(e);
				return new ContributedCleanUpTabPage(new ErrorPage(e));
			}
		}
	}

	private static class CleanUpDescriptor {

		private static final String ATTRIBUTE_ID_CLASS= "class"; //$NON-NLS-1$
		private static final String ATTRIBURE_ID_RUNAFTER= "runAfter"; //$NON-NLS-1$
		private static final String ATTRIBUTE_ID_ID= "id"; //$NON-NLS-1$

		private final IConfigurationElement fElement;
		private final String fId;
		private final String fRunAfter;

		/**
		 * @param element the configuration element
		 */
		public CleanUpDescriptor(IConfigurationElement element) {
			fElement= element;
			fId= element.getAttribute(ATTRIBUTE_ID_ID);
			fRunAfter= element.getAttribute(ATTRIBURE_ID_RUNAFTER);
		}

		/**
		 * @return the unique id of this clean up
		 */
		public String getId() {
			return fId;
		}

		/**
		 * @return the id of the clean up which must run before this clean up or
		 *         <strong>null</strong> if none specified
		 */
		public String getRunAfter() {
			return fRunAfter;
		}

		/**
		 * @return the clean up or <code>null</code> if the clean up could not be instantiated
		 */
		public ICleanUp createCleanUp() {
			try {
				return (ICleanUp)fElement.createExecutableExtension(ATTRIBUTE_ID_CLASS);
			} catch (CoreException e) {
				String msg= Messages.format(FixMessages.CleanUpRegistry_cleanUpCreation_error, new String[] { fElement.getAttribute(ATTRIBUTE_ID_ID), fElement.getContributor().getName() });
				JavaPlugin.logErrorStatus(msg, e.getStatus());
				return null;
			}
		}
	}

	private static final class CleanUpInitializerDescriptor {

		private static final String ATTRIBUTE_NAME_CLASS= "class"; //$NON-NLS-1$
		private static final String ATTRIBUTE_NAME_KIND= "cleanUpKind"; //$NON-NLS-1$

		private final IConfigurationElement fElement;

		private final int fKind;

		private ICleanUpOptionsInitializer fOptionsProvider;

		public CleanUpInitializerDescriptor(IConfigurationElement element) {
			fElement= element;
			String kind= fElement.getAttribute(ATTRIBUTE_NAME_KIND);
			fKind= getCleanUpKind(kind);
			if (fKind == -1)
				JavaPlugin.logErrorMessage(Messages.format(FixMessages.CleanUpRegistry_UnknownInitializerKind_errorMessage, new String[] { element.getContributor().getName(), kind }));
		}

		public int getKind() {
			return fKind;
		}

		public ICleanUpOptionsInitializer getOptionsInitializer() {
			if (fOptionsProvider == null) {
				try {
					fOptionsProvider= (ICleanUpOptionsInitializer)fElement.createExecutableExtension(ATTRIBUTE_NAME_CLASS);
				} catch (CoreException e) {
					JavaPlugin.log(e);
					fOptionsProvider= options -> {
					};
				}
			}
			return fOptionsProvider;
		}
	}

	private static final String EXTENSION_POINT_NAME= "cleanUps"; //$NON-NLS-1$
	private static final String CLEAN_UP_CONFIGURATION_ELEMENT_NAME= "cleanUp"; //$NON-NLS-1$
	private static final String TABPAGE_CONFIGURATION_ELEMENT_NAME= "cleanUpConfigurationUI"; //$NON-NLS-1$

	private static final String CLEAN_UP_INITIALIZER_CONFIGURATION_ELEMENT_NAME= "cleanUpOptionsInitializer"; //$NON-NLS-1$
	private static final String ATTRIBUTE_KIND_TYPE_SAVE_ACTION= "saveAction"; //$NON-NLS-1$
	private static final String ATTRIBUTE_KIND_TYPE_CLEAN_UP= "cleanUp"; //$NON-NLS-1$

	private CleanUpDescriptor[] fCleanUpDescriptors;
	private CleanUpTabPageDescriptor[] fPageDescriptors;

	private CleanUpInitializerDescriptor[] fCleanUpInitializerDescriptors;

	/**
	 * Creates and returns the registered clean ups that don't fail upon creation.
	 *
	 * @return an array of clean ups
	 */
	public synchronized ICleanUp[] createCleanUps() {
		return createCleanUps(null);
	}

	/**
	 * Creates and returns the registered clean ups that don't fail upon creation.
	 *
	 * @param ids the ids of the clean ups to create, or <code>null</code> to create all
	 * @return an array of clean ups
	 * @since 3.5
	 */
	public synchronized ICleanUp[] createCleanUps(Set<String> ids) {
		ensureCleanUpsRegistered();
		ArrayList<ICleanUp> result= new ArrayList<>(fCleanUpDescriptors.length);
		for (CleanUpDescriptor descriptor : fCleanUpDescriptors) {
			if (ids == null || ids.contains(descriptor.getId())) {
				ICleanUp cleanUp= descriptor.createCleanUp();
				if (cleanUp != null)
					result.add(cleanUp);
			}
		}
		return result.toArray(new ICleanUp[result.size()]);
	}

	/**
	 * @param kind the kind of clean up for which to retrieve the configuratin pages
	 *
	 * @return set of clean up tab page descriptors
	 *
	 * @see CleanUpConstants#DEFAULT_CLEAN_UP_OPTIONS
	 * @see CleanUpConstants#DEFAULT_SAVE_ACTION_OPTIONS
	 */
	public synchronized CleanUpTabPageDescriptor[] getCleanUpTabPageDescriptors(int kind) {
		ensurePagesRegistered();

		ArrayList<CleanUpTabPageDescriptor> result= new ArrayList<>();
		for (CleanUpTabPageDescriptor descriptor : fPageDescriptors) {
			if (descriptor.getKind() == kind) {
				result.add(descriptor);
			}
		}
		return result.toArray(new CleanUpTabPageDescriptor[result.size()]);
	}

	/**
	 * Returns the default options for the specified clean up kind.
	 *
	 * @param kind the kind of clean up for which to retrieve the options
	 * @return the default options
	 *
	 * @see CleanUpConstants#DEFAULT_CLEAN_UP_OPTIONS
	 * @see CleanUpConstants#DEFAULT_SAVE_ACTION_OPTIONS
	 */
	public MapCleanUpOptions getDefaultOptions(int kind) {
		ensureCleanUpInitializersRegistered();

		CleanUpOptions options= new CleanUpOptions();
		for (CleanUpInitializerDescriptor descriptor : fCleanUpInitializerDescriptors) {
			if (descriptor.getKind() == kind) {
				descriptor.getOptionsInitializer().setDefaultOptions(options);
			}
		}
		MapCleanUpOptions mapCleanUpOptions= new MapCleanUpOptions();
		mapCleanUpOptions.addAll(options);
		return mapCleanUpOptions;
	}

	private synchronized void ensureCleanUpsRegistered() {
		if (fCleanUpDescriptors != null)
			return;


		final ArrayList<CleanUpDescriptor> descriptors= new ArrayList<>();

		IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(JavaPlugin.getPluginId(), EXTENSION_POINT_NAME);
		for (IConfigurationElement element : point.getConfigurationElements()) {
			if (CLEAN_UP_CONFIGURATION_ELEMENT_NAME.equals(element.getName())) {
				descriptors.add(new CleanUpDescriptor(element));
			}
		}


		// Make sure we filter those who fail or misbehave
		for (int i= 0; i < descriptors.size(); i++) {
			final CleanUpDescriptor cleanUpDescriptor= descriptors.get(i);
			final boolean disable[]= new boolean[1];
			ISafeRunnable runnable= new SafeRunnable() {

				@Override
				public void run() throws Exception {
					ICleanUp cleanUp= cleanUpDescriptor.createCleanUp();
					if (cleanUp == null)
						disable[0]= true;
					else {
						cleanUp.setOptions(new CleanUpOptions());
						String[] enbledSteps= cleanUp.getStepDescriptions();
						if (enbledSteps != null && enbledSteps.length > 0) {
							JavaPlugin.logErrorMessage(
									Messages.format(FixMessages.CleanUpRegistry_cleanUpAlwaysEnabled_error, new String[] { cleanUpDescriptor.getId(),
									cleanUpDescriptor.fElement.getContributor().getName() }));
							disable[0]= true;
						}
					}
				}
				@Override
				public void handleException(Throwable t) {
					disable[0]= true;
					String message= Messages.format(FixMessages.CleanUpRegistry_cleanUpCreation_error, new String[] { cleanUpDescriptor.getId(),
							cleanUpDescriptor.fElement.getContributor().getName() });
					IStatus status= new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, t);
					JavaPlugin.log(status);
				}

			};
			SafeRunner.run(runnable);
			if (disable[0])
				descriptors.remove(i--);
		}

		fCleanUpDescriptors= descriptors.toArray(new CleanUpDescriptor[descriptors.size()]);
		sort(fCleanUpDescriptors);

	}

	private static void sort(CleanUpDescriptor[] data) {
		int lastSwapI= -1;
		int lastSwapJ= -1;
		mainLoop: for (int i= 0; i < data.length; i++) {
			String runAfter= data[i].getRunAfter();
			if (runAfter == null)
				continue;
			int jStart= i + 1;
			for (int j= jStart; j < data.length; j++) {
				String jID= data[j].getId();
				if (runAfter.equals(jID)) {
					if (lastSwapI == i && j >= lastSwapJ) {
						JavaPlugin.logErrorMessage("Problem reading cleanUps extensions: cannot satisfy rule for '" + data[i].getId() + "' to runAfter '" + runAfter + "'");   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
						continue mainLoop;
					}
					lastSwapI= i;
					lastSwapJ= j;
					swap(data, i, j);
					i--;
					continue mainLoop;
				}
			}
			for (int j= 0; j < jStart; j++) {
				String jID= data[j].getId();
				if (runAfter.equals(jID))
					continue mainLoop;
			}
			JavaPlugin.logErrorMessage("Problem reading cleanUps extensions: cannot satisfy rule for '" + data[i].getId() + "' to runAfter '" + runAfter + "' because the runAfter clean up does not exist."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
	}

	private static void swap(CleanUpDescriptor[] data, int i, int j) {
		CleanUpDescriptor o= data[i];
		data[i]= data[j];
		data[j]= o;
	}

	private synchronized void ensurePagesRegistered() {
		if (fPageDescriptors != null)
			return;

		ArrayList<CleanUpTabPageDescriptor> result= new ArrayList<>();

		IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(JavaPlugin.getPluginId(), EXTENSION_POINT_NAME);
		for (IConfigurationElement element : point.getConfigurationElements()) {
			if (TABPAGE_CONFIGURATION_ELEMENT_NAME.equals(element.getName())) {
				result.add(new CleanUpTabPageDescriptor(element));
			}
		}

		fPageDescriptors= result.toArray(new CleanUpTabPageDescriptor[result.size()]);
		Arrays.sort(fPageDescriptors, (o1, o2) -> {
			String name1= o1.getName();
			String name2= o2.getName();
			return Collator.getInstance().compare(name1.replaceAll("&", ""), name2.replaceAll("&", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		});
	}

	private synchronized void ensureCleanUpInitializersRegistered() {
		if (fCleanUpInitializerDescriptors != null)
			return;

		ArrayList<CleanUpInitializerDescriptor> result= new ArrayList<>();

		IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(JavaPlugin.getPluginId(), EXTENSION_POINT_NAME);
		for (IConfigurationElement element : point.getConfigurationElements()) {
			if (CLEAN_UP_INITIALIZER_CONFIGURATION_ELEMENT_NAME.equals(element.getName())) {
				result.add(new CleanUpInitializerDescriptor(element));
			}
		}

		fCleanUpInitializerDescriptors= result.toArray(new CleanUpInitializerDescriptor[result.size()]);
	}

	private static int getCleanUpKind(String kind) {
		switch (kind) {
		case ATTRIBUTE_KIND_TYPE_CLEAN_UP:
			return CleanUpConstants.DEFAULT_CLEAN_UP_OPTIONS;
		case ATTRIBUTE_KIND_TYPE_SAVE_ACTION:
			return CleanUpConstants.DEFAULT_SAVE_ACTION_OPTIONS;
		default:
			return -1;
		}
	}

}
