/*******************************************************************************
 * Copyright (c) 2000, 2020 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.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.swt.widgets.Display;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.text.edits.UndoEdit;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;

import org.eclipse.ltk.core.refactoring.CategorizedTextEditGroup;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.ContentStamp;
import org.eclipse.ltk.core.refactoring.GroupCategory;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.ltk.core.refactoring.NullChange;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringTickProvider;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.TextEditBasedChangeGroup;
import org.eclipse.ltk.core.refactoring.TextFileChange;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTRequestor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;

import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.dom.ASTBatchParser;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.MultiStateCompilationUnitChange;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.refactoring.util.TextEditUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.cleanup.CleanUpContext;
import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
import org.eclipse.jdt.ui.cleanup.ICleanUp;
import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
import org.eclipse.jdt.ui.text.java.IProblemLocation;

import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.fix.IMultiFix.MultiFixContext;
import org.eclipse.jdt.internal.ui.fix.MapCleanUpOptions;
import org.eclipse.jdt.internal.ui.refactoring.IScheduledRefactoring;

public class CleanUpRefactoring extends Refactoring implements IScheduledRefactoring {

	public static class CleanUpTarget {

		private final ICompilationUnit fCompilationUnit;

		public CleanUpTarget(ICompilationUnit unit) {
			fCompilationUnit= unit;
		}

		public ICompilationUnit getCompilationUnit() {
			return fCompilationUnit;
		}
	}

	public static class MultiFixTarget extends CleanUpTarget {

		private final IProblemLocation[] fProblems;

		public MultiFixTarget(ICompilationUnit unit, IProblemLocation[] problems) {
			super(unit);
			fProblems= problems;
		}

		public IProblemLocation[] getProblems() {
			return fProblems;
		}
	}

	public static class CleanUpChange extends CompilationUnitChange {

		private UndoEdit fUndoEdit;

		public CleanUpChange(String name, ICompilationUnit cunit) {
	        super(name, cunit);
        }

		@Override
		protected Change createUndoChange(UndoEdit edit, ContentStamp stampToRestore) {
		    fUndoEdit= edit;
			return super.createUndoChange(edit, stampToRestore);
		}

		public UndoEdit getUndoEdit() {
        	return fUndoEdit;
        }

		/*
		 * @see org.eclipse.ltk.core.refactoring.TextChange#perform(org.eclipse.core.runtime.IProgressMonitor)
		 */
		@Override
		public Change perform(final IProgressMonitor pm) throws CoreException {
			if (Display.getCurrent() == null) {
				final Change[] result= new Change[1];
				final CoreException[] exs= new CoreException[1];
				Display.getDefault().syncExec(() -> {
					try {
						result[0]= CleanUpChange.super.perform(pm);
					} catch (CoreException e) {
						exs[0]= e;
					}
				});

				if (exs[0] != null) {
					IStatus status= new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, Messages.format(FixMessages.CleanUpRefactoring_exception,
							getCompilationUnit().getResource().getFullPath().toString()), exs[0]);
					throw new CoreException(status);
				}

				return result[0];
			} else {
				return super.perform(pm);
			}
		}
	}

	private static class FixCalculationException extends RuntimeException {

		private static final long serialVersionUID= 3807273310144726165L;

		private final CoreException fException;

		public FixCalculationException(CoreException exception) {
			fException= exception;
		}

		public CoreException getException() {
			return fException;
		}
	}

	private static class ParseListElement {

		private final CleanUpTarget fTarget;
		private final ICleanUp[] fCleanUpsArray;

		public ParseListElement(CleanUpTarget cleanUpTarget, ICleanUp[] cleanUps) {
			fTarget= cleanUpTarget;
			fCleanUpsArray= cleanUps;
		}

		public CleanUpTarget getTarget() {
			return fTarget;
		}

		public ICleanUp[] getCleanUps() {
			return fCleanUpsArray;
		}
	}

	private final class CleanUpRefactoringProgressMonitor extends SubProgressMonitor {

		private double fRealWork;
		private int fFlushCount;
		private final int fSize;
		private final int fIndex;

		private CleanUpRefactoringProgressMonitor(IProgressMonitor monitor, int ticks, int size, int index) {
			super(monitor, ticks);
			fFlushCount= 0;
			fSize= size;
			fIndex= index;
		}

		@Override
		public void internalWorked(double work) {
			fRealWork+= work;
		}

		public void flush() {
			super.internalWorked(fRealWork);
			reset();
			fFlushCount++;
		}

		public void reset() {
			fRealWork= 0.0;
		}

		@Override
		public void done() {}

		public int getIndex() {
			return fIndex + fFlushCount;
		}

		public String getSubTaskMessage(ICompilationUnit source) {
			String typeName= BasicElementLabels.getFileName(source);
			return Messages.format(FixMessages.CleanUpRefactoring_ProcessingCompilationUnit_message, new Object[] {Integer.valueOf(getIndex()), Integer.valueOf(fSize), typeName});
		}
	}

	private static class CleanUpASTRequestor extends ASTRequestor {

		private final List<ParseListElement> fUndoneElements;
		private final Hashtable<ICompilationUnit, List<CleanUpChange>> fSolutions;
		private final Hashtable<ICompilationUnit, ParseListElement> fCompilationUnitParseElementMap;
		private final CleanUpRefactoringProgressMonitor fMonitor;

		public CleanUpASTRequestor(List<ParseListElement> parseList, Hashtable<ICompilationUnit, List<CleanUpChange>> solutions, CleanUpRefactoringProgressMonitor monitor) {
			fSolutions= solutions;
			fMonitor= monitor;
			fUndoneElements= new ArrayList<>();
			fCompilationUnitParseElementMap= new Hashtable<>(parseList.size());
			for (ParseListElement element : parseList) {
				fCompilationUnitParseElementMap.put(element.getTarget().getCompilationUnit(), element);
			}
		}

		@Override
		public void acceptAST(ICompilationUnit source, CompilationUnit ast) {

			fMonitor.subTask(fMonitor.getSubTaskMessage(source));

			ICompilationUnit primary= (ICompilationUnit)source.getPrimaryElement();
			ParseListElement element= fCompilationUnitParseElementMap.get(primary);
			CleanUpTarget target= element.getTarget();

			CleanUpContext context;
			if (target instanceof MultiFixTarget) {
				context= new MultiFixContext(source, ast, ((MultiFixTarget)target).getProblems());
			} else {
				context= new CleanUpContext(source, ast);
			}
			ICleanUp[] rejectedCleanUps= calculateSolutions(context, element.getCleanUps());

			if (rejectedCleanUps.length > 0) {
				fUndoneElements.add(new ParseListElement(target, rejectedCleanUps));
				fMonitor.reset();
			} else {
				fMonitor.flush();
			}
		}

		public void acceptSource(ICompilationUnit source) {
			acceptAST(source, null);
		}

		public List<ParseListElement> getUndoneElements() {
			return fUndoneElements;
		}

		private ICleanUp[] calculateSolutions(CleanUpContext context, ICleanUp[] cleanUps) {
			List<ICleanUp>result= new ArrayList<>();
			CleanUpChange solution;
			try {
				solution= calculateChange(context, cleanUps, result, null);
			} catch (CoreException e) {
				throw new FixCalculationException(e);
			}

			if (solution != null) {
				integrateSolution(solution, context.getCompilationUnit());
			}

			return result.toArray(new ICleanUp[result.size()]);
		}

		private void integrateSolution(CleanUpChange solution, ICompilationUnit source) {
			ICompilationUnit primary= source.getPrimary();

			List<CleanUpChange> changes= fSolutions.get(primary);
			if (changes == null) {
				changes= new ArrayList<>();
				fSolutions.put(primary, changes);
			}
			changes.add(solution);
		}
	}

	private class CleanUpFixpointIterator {

		private List<ParseListElement> fParseList;
		private final Hashtable<ICompilationUnit, List<CleanUpChange>> fSolutions;
		private final Hashtable<ICompilationUnit, ICompilationUnit> fWorkingCopies; // map from primary to working copy
		private final Map<String, String> fCleanUpOptions;
		private final int fSize;
		private int fIndex;

		public CleanUpFixpointIterator(CleanUpTarget[] targets, ICleanUp[] cleanUps) {
			fSolutions= new Hashtable<>(targets.length);
			fWorkingCopies= new Hashtable<>();

			fParseList= new ArrayList<>(targets.length);
			for (CleanUpTarget target : targets) {
				fParseList.add(new ParseListElement(target, cleanUps));
			}

			fCleanUpOptions= new Hashtable<>();
			for (ICleanUp cleanUp : cleanUps) {
				Map<String, String> currentCleanUpOption= cleanUp.getRequirements().getCompilerOptions();
				if (currentCleanUpOption != null)
					fCleanUpOptions.putAll(currentCleanUpOption);
			}

			fSize= targets.length;
			fIndex= 1;
		}

		public boolean hasNext() {
			return !fParseList.isEmpty();
		}

		public void next(IProgressMonitor monitor) throws CoreException {
			List<ICompilationUnit> parseList= new ArrayList<>();
			List<ICompilationUnit> sourceList= new ArrayList<>();

			try {
				for (ParseListElement element : fParseList) {
					ICompilationUnit compilationUnit= element.getTarget().getCompilationUnit();
					if (fSolutions.containsKey(compilationUnit)) {
						if (fWorkingCopies.containsKey(compilationUnit)) {
							compilationUnit= fWorkingCopies.get(compilationUnit);
						} else {
							compilationUnit= compilationUnit.getWorkingCopy(new WorkingCopyOwner() {}, null);
							fWorkingCopies.put(compilationUnit.getPrimary(), compilationUnit);
						}
						applyChange(compilationUnit, fSolutions.get(compilationUnit.getPrimary()));
					}

					if (requiresAST(element.getCleanUps())) {
						parseList.add(compilationUnit);
					} else {
						sourceList.add(compilationUnit);
					}
				}

				CleanUpRefactoringProgressMonitor cuMonitor= new CleanUpRefactoringProgressMonitor(monitor, parseList.size() + sourceList.size(), fSize, fIndex);
				CleanUpASTRequestor requestor= new CleanUpASTRequestor(fParseList, fSolutions, cuMonitor);
				if (parseList.size() > 0) {
					ASTBatchParser parser= new ASTBatchParser() {
						@Override
						protected ASTParser createParser(IJavaProject project) {
							ASTParser result= createCleanUpASTParser();
							result.setProject(project);

							Map<String, String> options= RefactoringASTParser.getCompilerOptions(project);
							options.putAll(fCleanUpOptions);
							result.setCompilerOptions(options);
							return result;
						}
					};
					try {
						ICompilationUnit[] units= parseList.toArray(new ICompilationUnit[parseList.size()]);
						parser.createASTs(units, new String[0], requestor, cuMonitor);
					} catch (FixCalculationException e) {
						throw e.getException();
					}
				}

				for (ICompilationUnit cu : sourceList) {
					monitor.worked(1);

					requestor.acceptSource(cu);

					if (monitor.isCanceled())
						throw new OperationCanceledException();
				}

				fParseList= requestor.getUndoneElements();
				fIndex= cuMonitor.getIndex();
			} finally {
			}
		}

		public void dispose() {
			for (ICompilationUnit cu : fWorkingCopies.values()) {
				try {
					cu.discardWorkingCopy();
				} catch (JavaModelException e) {
					JavaPlugin.log(e);
				}
			}
			fWorkingCopies.clear();
		}

		private boolean requiresAST(ICleanUp[] cleanUps) {
			for (ICleanUp cleanUp : cleanUps) {
				if (cleanUp.getRequirements().requiresAST()) {
					return true;
				}
			}
			return false;
		}

		public Change[] getResult() {

			Change[] result= new Change[fSolutions.size()];
			int i=0;
			for (Entry<ICompilationUnit, List<CleanUpChange>> entry : fSolutions.entrySet()) {
				List<CleanUpChange> changes= entry.getValue();
				ICompilationUnit unit= entry.getKey();

				int saveMode;
				if (fLeaveFilesDirty) {
					saveMode= TextFileChange.LEAVE_DIRTY;
				} else {
					saveMode= TextFileChange.KEEP_SAVE_STATE;
				}

				if (changes.size() == 1) {
					CleanUpChange change= changes.get(0);
					change.setSaveMode(saveMode);
					result[i]= change;
				} else {
					MultiStateCompilationUnitChange mscuc= new MultiStateCompilationUnitChange(getChangeName(unit), unit);
					for (CleanUpChange change : changes) {
						mscuc.addChange(createGroupFreeChange(change));
					}
					mscuc.setSaveMode(saveMode);
					result[i]= mscuc;
				}

				i++;
			}

			return result;
		}

		private TextChange createGroupFreeChange(CleanUpChange change) {
			CleanUpChange result= new CleanUpChange(change.getName(), change.getCompilationUnit());
			result.setEdit(change.getEdit());
			result.setSaveMode(change.getSaveMode());
	        return result;
        }

		private void applyChange(ICompilationUnit compilationUnit, List<CleanUpChange> changes) throws JavaModelException, CoreException {
			IDocument document= new Document(changes.get(0).getCurrentContent(new NullProgressMonitor()));
			for (CleanUpChange change : changes) {
				TextEdit edit= change.getEdit().copy();

				try {
					edit.apply(document, TextEdit.UPDATE_REGIONS);
				} catch (MalformedTreeException | BadLocationException e) {
					JavaPlugin.log(e);
				}
			}
			compilationUnit.getBuffer().setContents(document.get());
		}
	}

	private static final RefactoringTickProvider CLEAN_UP_REFACTORING_TICK_PROVIDER= new RefactoringTickProvider(0, 1, 0, 0);

	/**
	 * A clean up is considered slow if its execution lasts longer then the value of
	 * SLOW_CLEAN_UP_THRESHOLD in ms.
	 */
	private static final int SLOW_CLEAN_UP_THRESHOLD= 2000;

	private final List<ICleanUp> fCleanUps;
	private final Hashtable<IJavaProject, List<CleanUpTarget>> fProjects;
	private Change fChange;
	private boolean fLeaveFilesDirty;
	private final String fName;

	private boolean fUseOptionsFromProfile;

	public CleanUpRefactoring() {
		this(FixMessages.CleanUpRefactoring_Refactoring_name);
	}

	public CleanUpRefactoring(String name) {
		fName= name;
		fCleanUps= new ArrayList<>();
		fProjects= new Hashtable<>();
		fUseOptionsFromProfile= false;
	}

	public void setUseOptionsFromProfile(boolean enabled) {
		fUseOptionsFromProfile= enabled;
	}

	public void addCompilationUnit(ICompilationUnit unit) {
		addCleanUpTarget(new CleanUpTarget(unit));
	}

	public void addCleanUpTarget(CleanUpTarget target) {

		IJavaProject javaProject= target.getCompilationUnit().getJavaProject();
		if (!fProjects.containsKey(javaProject))
			fProjects.put(javaProject, new ArrayList<CleanUpTarget>());

		List<CleanUpTarget> targets= fProjects.get(javaProject);
		targets.add(target);
	}

	public CleanUpTarget[] getCleanUpTargets() {
		List<CleanUpTarget> result= new ArrayList<>();
		for (List<CleanUpTarget> projectTargets : fProjects.values()) {
			result.addAll(projectTargets);
		}
		return result.toArray(new CleanUpTarget[result.size()]);
	}

	public int getCleanUpTargetsSize() {
		int result= 0;
		for (List<CleanUpTarget> projectTargets : fProjects.values()) {
			result+= projectTargets.size();
		}
		return result;
	}

	public void addCleanUp(ICleanUp fix) {
		fCleanUps.add(fix);
	}

	public void clearCleanUps() {
		fCleanUps.clear();
	}

	public boolean hasCleanUps() {
		return !fCleanUps.isEmpty();
	}

	public ICleanUp[] getCleanUps() {
		return fCleanUps.toArray(new ICleanUp[fCleanUps.size()]);
	}

	public IJavaProject[] getProjects() {
		return fProjects.keySet().toArray(new IJavaProject[fProjects.size()]);
	}

	public void setLeaveFilesDirty(boolean leaveFilesDirty) {
		fLeaveFilesDirty= leaveFilesDirty;
	}

	@Override
	public String getName() {
		return fName;
	}

	@Override
	public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
		if (pm != null) {
			pm.beginTask("", 1); //$NON-NLS-1$
			pm.worked(1);
			pm.done();
		}
		return new RefactoringStatus();
	}

	@Override
	public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
		if (pm != null) {
			pm.beginTask("", 1); //$NON-NLS-1$
			pm.worked(1);
			pm.done();
		}
		return fChange;
	}

	@Override
	public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {

		if (pm == null)
			pm= new NullProgressMonitor();

		if (fProjects.isEmpty() || fCleanUps.isEmpty()) {
			pm.beginTask("", 1); //$NON-NLS-1$
			pm.worked(1);
			pm.done();
			fChange= new NullChange();

			return new RefactoringStatus();
		}

		int cuCount= getCleanUpTargetsSize();

		RefactoringStatus result= new RefactoringStatus();

		ICleanUp[] cleanUps= getCleanUps();
		pm.beginTask("", cuCount * 2 * fCleanUps.size() + 4 * cleanUps.length); //$NON-NLS-1$
		try {
			DynamicValidationStateChange change= new DynamicValidationStateChange(getName());
			change.setSchedulingRule(getSchedulingRule());
			for (Entry<IJavaProject, List<CleanUpTarget>> entry : fProjects.entrySet()) {
				IJavaProject project= entry.getKey();
				List<CleanUpTarget> targetsList= entry.getValue();
				CleanUpTarget[] targets= targetsList.toArray(new CleanUpTarget[targetsList.size()]);
				if (fUseOptionsFromProfile) {
					result.merge(setOptionsFromProfile(project, cleanUps));
					if (result.hasFatalError())
						return result;
				}
				result.merge(checkPreConditions(project, targets, new SubProgressMonitor(pm, 3 * cleanUps.length)));
				if (result.hasFatalError())
					return result;
				Change[] changes= cleanUpProject(project, targets, cleanUps, pm);
				result.merge(checkPostConditions(new SubProgressMonitor(pm, cleanUps.length)));
				if (result.hasFatalError())
					return result;
				for (Change c : changes) {
					change.add(c);
				}
			}
			fChange= change;

			List<IResource> files= new ArrayList<>();
			findFilesToBeModified(change, files);
			result.merge(Checks.validateModifiesFiles(files.toArray(new IFile[files.size()]), getValidationContext(), pm));
		} finally {
			pm.done();
		}

		return result;
	}

	private void findFilesToBeModified(CompositeChange change, List<IResource> result) throws JavaModelException {
		for (Change child : change.getChildren()) {
			if (child instanceof CompositeChange) {
				findFilesToBeModified((CompositeChange)child, result);
			} else if (child instanceof MultiStateCompilationUnitChange) {
				result.add(((MultiStateCompilationUnitChange)child).getCompilationUnit().getCorrespondingResource());
			} else if (child instanceof CompilationUnitChange) {
				result.add(((CompilationUnitChange)child).getCompilationUnit().getCorrespondingResource());
			}
		}
	}

	private Change[] cleanUpProject(IJavaProject project, CleanUpTarget[] targets, ICleanUp[] cleanUps, IProgressMonitor monitor) throws CoreException {
		CleanUpFixpointIterator iter= new CleanUpFixpointIterator(targets, cleanUps);

		SubProgressMonitor subMonitor= new SubProgressMonitor(monitor, 2 * targets.length * cleanUps.length);
		subMonitor.beginTask("", targets.length); //$NON-NLS-1$
		subMonitor.subTask(Messages.format(FixMessages.CleanUpRefactoring_Parser_Startup_message, BasicElementLabels.getResourceName(project.getProject())));
		try {
			while (iter.hasNext()) {
				iter.next(subMonitor);
			}

			return iter.getResult();
		} finally {
			iter.dispose();
			subMonitor.done();
		}
	}

	private RefactoringStatus setOptionsFromProfile(IJavaProject javaProject, ICleanUp[] cleanUps) {
		Map<String, String> options= CleanUpPreferenceUtil.loadOptions(new ProjectScope(javaProject.getProject()));
		if (options == null)
			return RefactoringStatus.createFatalErrorStatus(Messages.format(FixMessages.CleanUpRefactoring_could_not_retrive_profile, BasicElementLabels.getResourceName(javaProject.getProject())));

		CleanUpOptions cleanUpOptions= new MapCleanUpOptions(options);
		for (ICleanUp cleanUp : cleanUps) {
			cleanUp.setOptions(cleanUpOptions);
		}

		return new RefactoringStatus();
	}

	private RefactoringStatus checkPreConditions(IJavaProject javaProject, CleanUpTarget[] targets, IProgressMonitor monitor) throws CoreException {
		RefactoringStatus result= new RefactoringStatus();

		ICompilationUnit[] compilationUnits= new ICompilationUnit[targets.length];
		for (int i= 0; i < targets.length; i++) {
			compilationUnits[i]= targets[i].getCompilationUnit();
		}

		ICleanUp[] cleanUps= getCleanUps();
		monitor.beginTask("", compilationUnits.length * cleanUps.length); //$NON-NLS-1$
		monitor.subTask(Messages.format(FixMessages.CleanUpRefactoring_Initialize_message, BasicElementLabels.getResourceName(javaProject.getProject())));
		try {
			for (ICleanUp cleanUp : cleanUps) {
				result.merge(cleanUp.checkPreConditions(javaProject, compilationUnits, new SubProgressMonitor(monitor, compilationUnits.length)));
				if (result.hasFatalError())
					return result;
			}
		} finally {
			monitor.done();
		}

		return result;
	}

	private RefactoringStatus checkPostConditions(SubProgressMonitor monitor) throws CoreException {
		RefactoringStatus result= new RefactoringStatus();

		ICleanUp[] cleanUps= getCleanUps();
		monitor.beginTask("", cleanUps.length); //$NON-NLS-1$
		monitor.subTask(FixMessages.CleanUpRefactoring_checkingPostConditions_message);
		try {
			for (ICleanUp cleanUp : cleanUps) {
				result.merge(cleanUp.checkPostConditions(new SubProgressMonitor(monitor, 1)));
			}
		} finally {
			monitor.done();
		}
		return result;
	}

	private static String getChangeName(ICompilationUnit compilationUnit) {
		StringBuffer buf= new StringBuffer();
		JavaElementLabels.getCompilationUnitLabel(compilationUnit, JavaElementLabels.ALL_DEFAULT, buf);
		buf.append(JavaElementLabels.CONCAT_STRING);

		StringBuffer buf2= new StringBuffer();
		JavaElementLabels.getPackageFragmentLabel((IPackageFragment)compilationUnit.getParent(), JavaElementLabels.P_QUALIFIED, buf2);
		buf.append(buf2.toString().replace('.', '/'));

		return buf.toString();
	}

	public static CleanUpChange calculateChange(CleanUpContext context, ICleanUp[] cleanUps, List<ICleanUp> undoneCleanUps, HashSet<ICleanUp> slowCleanUps) throws CoreException {
		if (cleanUps.length == 0)
			return null;

		CleanUpChange solution= null;
		int i= 0;
		do {
			ICleanUp cleanUp= cleanUps[i];
			ICleanUpFix fix;
			if (slowCleanUps != null) {
				long timeBefore= System.currentTimeMillis();
				fix= cleanUp.createFix(context);
				if (System.currentTimeMillis() - timeBefore > SLOW_CLEAN_UP_THRESHOLD)
					slowCleanUps.add(cleanUp);
			} else {
				fix= cleanUp.createFix(context);
			}
			if (fix != null) {
				CompilationUnitChange current= fix.createChange(null);
				TextEdit currentEdit= current.getEdit();

				if (solution != null) {
					if (TextEditUtil.overlaps(currentEdit, solution.getEdit())) {
						undoneCleanUps.add(cleanUp);
					} else {
						CleanUpChange merge= new CleanUpChange(FixMessages.CleanUpRefactoring_clean_up_multi_chang_name, context.getCompilationUnit());
						merge.setEdit(TextEditUtil.merge(currentEdit, solution.getEdit()));

						copyChangeGroups(merge, solution);
						copyChangeGroups(merge, current);

						solution= merge;
					}
				} else {
					solution= new CleanUpChange(current.getName(), context.getCompilationUnit());
					solution.setEdit(currentEdit);

					copyChangeGroups(solution, current);
				}
			}
			i++;
		} while (i < cleanUps.length && (context.getAST() == null || !cleanUps[i].getRequirements().requiresFreshAST()));

		for (; i < cleanUps.length; i++) {
			undoneCleanUps.add(cleanUps[i]);
		}
		return solution;
	}

	private static void copyChangeGroups(CompilationUnitChange target, CompilationUnitChange source) {
		for (TextEditBasedChangeGroup changeGroup : source.getChangeGroups()) {
			TextEditGroup textEditGroup= changeGroup.getTextEditGroup();
			TextEditGroup newGroup;
			if (textEditGroup instanceof CategorizedTextEditGroup) {
				String label= textEditGroup.getName();
				newGroup= new CategorizedTextEditGroup(label, new GroupCategorySet(new GroupCategory(label, label, label)));
			} else {
				newGroup= new TextEditGroup(textEditGroup.getName());
			}
			for (TextEdit textEdit : textEditGroup.getTextEdits()) {
				newGroup.addTextEdit(textEdit);
			}
			target.addTextEditGroup(newGroup);
		}
	}

	@Override
	protected RefactoringTickProvider doGetRefactoringTickProvider() {
		return CLEAN_UP_REFACTORING_TICK_PROVIDER;
	}

	@Override
	public ISchedulingRule getSchedulingRule() {
		return ResourcesPlugin.getWorkspace().getRoot();
	}

	public static ASTParser createCleanUpASTParser() {
		ASTParser result= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);

		result.setResolveBindings(true);
		result.setStatementsRecovery(IASTSharedValues.SHARED_AST_STATEMENT_RECOVERY);
		result.setBindingsRecovery(IASTSharedValues.SHARED_BINDING_RECOVERY);

		return result;
	}

}
