/*******************************************************************************
 * Copyright (c) 2005-2008 Bastian Doetsch and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * bastian	implementation
 *     Andrei Loskutov (Intland) - bug fixes
 *******************************************************************************/
package com.vectrace.MercurialEclipse.operations;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ui.IWorkbenchPart;

import com.vectrace.MercurialEclipse.actions.HgOperation;
import com.vectrace.MercurialEclipse.commands.HgClients;
import com.vectrace.MercurialEclipse.commands.HgIdentClient;
import com.vectrace.MercurialEclipse.commands.HgPatchClient;
import com.vectrace.MercurialEclipse.commands.HgStatusClient;
import com.vectrace.MercurialEclipse.commands.HgUpdateClient;
import com.vectrace.MercurialEclipse.commands.RefreshWorkspaceStatusJob;
import com.vectrace.MercurialEclipse.commands.extensions.HgAtticClient;
import com.vectrace.MercurialEclipse.exception.HgException;
import com.vectrace.MercurialEclipse.model.HgRoot;
import com.vectrace.MercurialEclipse.team.MercurialUtilities;
import com.vectrace.MercurialEclipse.team.ResourceProperties;

/**
 * @author bastian
 */
public class ShelveOperation extends HgOperation {
	private final HgRoot hgRoot;

	public ShelveOperation(IWorkbenchPart part, HgRoot hgRoot) {
		super(part);
		this.hgRoot = hgRoot;
	}

	@Override
	protected String getActionDescription() {
		return Messages.getString("ShelveOperation.shelvingChanges"); //$NON-NLS-1$
	}

	@Override
	public void run(IProgressMonitor monitor) throws InvocationTargetException,
			InterruptedException {
		try {
			// get modified files
			monitor.beginTask(Messages.getString("ShelveOperation.shelving"), 5); //$NON-NLS-1$
			// check if hgattic is available
			if (MercurialUtilities.isCommandAvailable("attic-shelve",// $NON-NLS-1$
							ResourceProperties.EXT_HGATTIC_AVAILABLE, "")) { // $NON-NLS-1$
				String output = HgAtticClient.shelve(hgRoot,
						"MercurialEclipse shelve operation", // $NON-NLS-1$
						true, MercurialUtilities.getHGUsername(),
						hgRoot.getName());
				monitor.worked(1);
				new RefreshWorkspaceStatusJob(hgRoot, true).schedule();
				monitor.worked(1);
				HgClients.getConsole().printMessage(output, null);
			} else {

				monitor.subTask(Messages.getString("ShelveOperation.determiningChanges")); //$NON-NLS-1$
				Set<IPath> resources = getDirtyFiles(hgRoot);
				if (resources.size() == 0) {
					throw new HgException(Messages.getString("ShelveOperation.error.nothingToShelve")); //$NON-NLS-1$
				}
				monitor.worked(1);
				monitor.subTask(Messages.getString("ShelveOperation.shelvingChanges")); //$NON-NLS-1$

				File shelveDir = new File(hgRoot, ".hg" + File.separator //$NON-NLS-1$
						+ "mercurialeclipse-shelve-backups"); //$NON-NLS-1$
				boolean mkdir = shelveDir.mkdir();
				if(!mkdir && !shelveDir.exists()){
					throw new HgException(Messages.getString("ShelveOperation.error.shelfDirCreateFailed")); //$NON-NLS-1$
				}
				File shelveFile = new File(shelveDir, hgRoot.getName() + "-patchfile.patch"); //$NON-NLS-1$
				if (shelveFile.exists()) {
					throw new HgException(Messages.getString("ShelveOperation.error.shelfNotEmpty")); //$NON-NLS-1$
				}
				HgPatchClient.exportPatch(hgRoot, resources, shelveFile, new ArrayList<String>(0));
				monitor.worked(1);
				monitor.subTask(Messages.getString("ShelveOperation.determiningCurrentChangeset")); //$NON-NLS-1$
				String currRev = HgIdentClient.getCurrentChangesetId(hgRoot);
				monitor.worked(1);
				monitor.subTask(Messages.getString("ShelveOperation.cleaningDirtyFiles")); //$NON-NLS-1$
				HgUpdateClient.update(hgRoot, currRev, true);
			}
		} catch (CoreException e) {
			throw new InvocationTargetException(e, e.getLocalizedMessage());
		} finally {
			monitor.done();
		}

	}

	private static Set<IPath> getDirtyFiles(HgRoot root) throws HgException {
		Set<IPath> filePaths = HgStatusClient.getDirtyFilePaths(root);
		Set<IPath> resources = new HashSet<IPath>();
		for (IPath path : filePaths) {
			// XXX we shelve only "changed" files, but we also should handle removed...
			if (path.toFile().exists()) {
				resources.add(path);
			}
		}
		return resources;
	}


}

@@ -2887,83 +2887,50 @@
 %09%09%09%09
-Set%3CIPath%3E resources = getDirtyFiles(hgRoot);%0A%09%09%09%09if (resources.size() == 0
+//%0A%09%09%09%09if (!HgStatusClient.isDirty(hgRoot)
 ) %7B%0A
@@ -3707,24 +3707,176 @@
 LS-1$%0A%09%09%09%09%7D%0A
+%09%09%09%09// use empty resources to be able to shelve ALL files, also deleted/added%0A%09%09%09%09Set%3CIPath%3E resources = new HashSet%3CIPath%3E();// getDirtyFiles(hgRoot);%0A
 %09%09%09%09HgPatchC
@@ -4453,401 +4453,10 @@
 %09%7D%0A%0A
+
 %09%7D%0A%0A
-%09private static Set%3CIPath%3E getDirtyFiles(HgRoot root) throws HgException %7B%0A%09%09Set%3CIPath%3E filePaths = HgStatusClient.getDirtyFilePaths(root);%0A%09%09Set%3CIPath%3E resources = new HashSet%3CIPath%3E();%0A%09%09for (IPath path : filePaths) %7B%0A%09%09%09// XXX we shelve only %22changed%22 files, but we also should handle removed...%0A%09%09%09if (path.toFile().exists()) %7B%0A%09%09%09%09resources.add(path);%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return resources;%0A%09%7D%0A%0A%0A
 %7D%0A

Fix for the shelve operation, which didn't saved diff of currently deleted files.