/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Created by IntelliJ IDEA.
 * User: yole
 * Date: 22.11.2006
 * Time: 19:59:36
 */
package com.intellij.openapi.vcs.changes.shelf;

import com.intellij.lifecycle.PeriodicalTasksCloser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.patch.*;
import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
import com.intellij.openapi.diff.impl.patch.formove.CustomBinaryPatchApplier;
import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
import com.intellij.openapi.progress.AsynchronousExecution;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectEx;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.patch.ApplyPatchDefaultExecutor;
import com.intellij.openapi.vcs.changes.patch.PatchFileType;
import com.intellij.openapi.vcs.changes.patch.PatchNameChecker;
import com.intellij.openapi.vcs.changes.ui.RollbackChangesDialog;
import com.intellij.openapi.vcs.changes.ui.RollbackWorker;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.intellij.util.PathUtil;
import com.intellij.util.SmartList;
import com.intellij.util.continuation.*;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.Topic;
import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcsUtil.FilesProgress;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.io.*;
import java.util.*;

import static com.intellij.openapi.vcs.changes.shelf.CompoundShelfFileProcessor.SHELF_DIR_NAME;

public class ShelveChangesManager extends AbstractProjectComponent implements JDOMExternalizable {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager");

  public static ShelveChangesManager getInstance(Project project) {
    return PeriodicalTasksCloser.getInstance().safeGetComponent(project, ShelveChangesManager.class);
  }

  private final MessageBus myBus;
  private final List<ShelvedChangeList> myShelvedChangeLists = new ArrayList<ShelvedChangeList>();
  private final List<ShelvedChangeList> myRecycledShelvedChangeLists = new ArrayList<ShelvedChangeList>();

  @NonNls private static final String ATTRIBUTE_SHOW_RECYCLED = "show_recycled";
  private final CompoundShelfFileProcessor myFileProcessor;

  public static final Topic<ChangeListener> SHELF_TOPIC = new Topic<ChangeListener>("shelf updates", ChangeListener.class);
  private boolean myShowRecycled;

  public ShelveChangesManager(final Project project, final MessageBus bus) {
    super(project);
    myBus = bus;
    if (project.isDefault()) {
      myFileProcessor = new CompoundShelfFileProcessor(null, PathManager.getConfigPath() + File.separator + SHELF_DIR_NAME);
    }
    else {
      if (project instanceof ProjectEx && ((ProjectEx)project).getStateStore().getStorageScheme() == StorageScheme.DIRECTORY_BASED) {
        String shelfBaseDirPath = project.getBaseDir().getPath() + File.separator + Project.DIRECTORY_STORE_FOLDER;
        myFileProcessor = new CompoundShelfFileProcessor(shelfBaseDirPath);
      }
      else {
        myFileProcessor = new CompoundShelfFileProcessor();
      }
    }
  }

  @Override
  @NonNls
  @NotNull
  public String getComponentName() {
    return "ShelveChangesManager";
  }

  @Override
  public void readExternal(Element element) throws InvalidDataException {
    //noinspection unchecked

    final String showRecycled = element.getAttributeValue(ATTRIBUTE_SHOW_RECYCLED);
    if (showRecycled != null) {
      myShowRecycled = Boolean.parseBoolean(showRecycled);
    } else {
      myShowRecycled = true;
    }

    readExternal(element, myShelvedChangeLists, myRecycledShelvedChangeLists);


  }

  public static void readExternal(final Element element, final List<ShelvedChangeList> changes, final List<ShelvedChangeList> recycled) throws InvalidDataException {
    changes.addAll(ShelvedChangeList.readChanges(element, false, true));

    recycled.addAll(ShelvedChangeList.readChanges(element, true, true));
  }

  @Override
  public void writeExternal(Element element) throws WriteExternalException {
    element.setAttribute(ATTRIBUTE_SHOW_RECYCLED, Boolean.toString(myShowRecycled));
    ShelvedChangeList.writeChanges(myShelvedChangeLists, myRecycledShelvedChangeLists, element);

  }

  public List<ShelvedChangeList> getShelvedChangeLists() {
    return Collections.unmodifiableList(myShelvedChangeLists);
  }

  public ShelvedChangeList shelveChanges(final Collection<Change> changes, final String commitMessage, final boolean rollback) throws IOException, VcsException {
    final List<Change> textChanges = new ArrayList<Change>();
    final List<ShelvedBinaryFile> binaryFiles = new ArrayList<ShelvedBinaryFile>();
    for(Change change: changes) {
      if (ChangesUtil.getFilePath(change).isDirectory()) {
        continue;
      }
      if (change.getBeforeRevision() instanceof BinaryContentRevision || change.getAfterRevision() instanceof BinaryContentRevision) {
        binaryFiles.add(shelveBinaryFile(change));
      }
      else {
        textChanges.add(change);
      }
    }

    final ShelvedChangeList changeList;
    try {
      File patchPath = getPatchPath(commitMessage);
      ProgressManager.checkCanceled();
      final List<FilePatch> patches = IdeaTextPatchBuilder.buildPatch(myProject, textChanges, myProject.getBaseDir().getPresentableUrl(), false);
      ProgressManager.checkCanceled();

      CommitContext commitContext = new CommitContext();
      baseRevisionsOfDvcsIntoContext(textChanges, commitContext);
      myFileProcessor.savePathFile(
        new CompoundShelfFileProcessor.ContentProvider(){
            @Override
            public void writeContentTo(final Writer writer, CommitContext commitContext) throws IOException {
              UnifiedDiffWriter.write(myProject, patches, writer, "\n", commitContext);
            }
          },
          patchPath, commitContext);

      changeList = new ShelvedChangeList(patchPath.toString(), commitMessage.replace('\n', ' '), binaryFiles);
      myShelvedChangeLists.add(changeList);
      ProgressManager.checkCanceled();

      if (rollback) {
        final String operationName = UIUtil.removeMnemonic(RollbackChangesDialog.operationNameByChanges(myProject, changes));
        new RollbackWorker(myProject, operationName).doRollback(changes, true, null, VcsBundle.message("shelve.changes.action"));
      }
    }
    finally {
      notifyStateChanged();
    }

    return changeList;
  }

  private void baseRevisionsOfDvcsIntoContext(List<Change> textChanges, CommitContext commitContext) {
    ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
    if (vcsManager.dvcsUsedInProject() && VcsConfiguration.getInstance(myProject).INCLUDE_TEXT_INTO_SHELF) {
      final Set<Change> big = SelectFilesToAddTextsToPatchPanel.getBig(textChanges);
      final ArrayList<FilePath> toKeep = new ArrayList<FilePath>();
      for (Change change : textChanges) {
        if (change.getBeforeRevision() == null || change.getAfterRevision() == null) continue;
        if (big.contains(change)) continue;
        FilePath filePath = ChangesUtil.getFilePath(change);
        final AbstractVcs vcs = vcsManager.getVcsFor(filePath);
        if (vcs != null && VcsType.distributed.equals(vcs.getType())) {
          toKeep.add(filePath);
        }
      }
      commitContext.putUserData(BaseRevisionTextPatchEP.ourPutBaseRevisionTextKey, true);
      commitContext.putUserData(BaseRevisionTextPatchEP.ourBaseRevisionPaths, toKeep);
    }
  }

  public ShelvedChangeList importFilePatches(final String fileName, final List<FilePatch> patches, final PatchEP[] patchTransitExtensions) throws IOException {
    try {
      final File patchPath = getPatchPath(fileName);
      myFileProcessor.savePathFile(
        new CompoundShelfFileProcessor.ContentProvider(){
            @Override
            public void writeContentTo(final Writer writer, CommitContext commitContext) throws IOException {
              UnifiedDiffWriter.write(myProject, patches, writer, "\n", patchTransitExtensions, commitContext);
            }
          },
          patchPath, new CommitContext());

      final ShelvedChangeList changeList = new ShelvedChangeList(patchPath.toString(), fileName.replace('\n', ' '), new SmartList<ShelvedBinaryFile>());
      myShelvedChangeLists.add(changeList);
      return changeList;
    } finally {
      notifyStateChanged();
    }
  }

  public List<VirtualFile> gatherPatchFiles(final Collection<VirtualFile> files) {
    final List<VirtualFile> result = new ArrayList<VirtualFile>();

    final LinkedList<VirtualFile> filesQueue = new LinkedList<VirtualFile>(files);
    while (! filesQueue.isEmpty()) {
      ProgressManager.checkCanceled();
      final VirtualFile file = filesQueue.removeFirst();
      if (file.isDirectory()) {
        filesQueue.addAll(Arrays.asList(file.getChildren()));
        continue;
      }
      if (PatchFileType.NAME.equals(file.getFileType().getName())) {
        result.add(file);
      }
    }

    return result;
  }

  public List<ShelvedChangeList> importChangeLists(final Collection<VirtualFile> files,
                                                   final Consumer<VcsException> exceptionConsumer) {
    final List<ShelvedChangeList> result = new ArrayList<ShelvedChangeList>(files.size());
    try {
      final FilesProgress filesProgress = new FilesProgress(files.size(), "Processing ");
      for (VirtualFile file : files) {
        filesProgress.updateIndicator(file);
        final String description = file.getNameWithoutExtension().replace('_', ' ');
        final File patchPath = getPatchPath(description);
        final ShelvedChangeList list = new ShelvedChangeList(patchPath.getPath(), description, new SmartList<ShelvedBinaryFile>(),
                                                             file.getTimeStamp());
        try {
          final List<TextFilePatch> patchesList = loadPatches(myProject, file.getPath(), new CommitContext());
          if (! patchesList.isEmpty()) {
            FileUtil.copy(new File(file.getPath()), patchPath);
            // add only if ok to read patch
            myShelvedChangeLists.add(list);
            result.add(list);
          }
        }
        catch (IOException e) {
          exceptionConsumer.consume(new VcsException(e));
        }
        catch (PatchSyntaxException e) {
          exceptionConsumer.consume(new VcsException(e));
        }
      }
    } finally {
      notifyStateChanged();
    }
    return result;
  }

  private ShelvedBinaryFile shelveBinaryFile(final Change change) throws IOException {
    final ContentRevision beforeRevision = change.getBeforeRevision();
    final ContentRevision afterRevision = change.getAfterRevision();
    File beforeFile = beforeRevision == null ? null : beforeRevision.getFile().getIOFile();
    File afterFile = afterRevision == null ? null : afterRevision.getFile().getIOFile();
    String shelvedPath = null;
    if (afterFile != null) {
      String shelvedName = FileUtil.getNameWithoutExtension(afterFile.getName());
      String shelvedExt = FileUtilRt.getExtension(afterFile.getName());
      File shelvedFile = FileUtil.findSequentNonexistentFile(myFileProcessor.getBaseIODir(), shelvedName, shelvedExt);

      myFileProcessor.saveFile(afterRevision.getFile().getIOFile(), shelvedFile);

      shelvedPath = shelvedFile.getPath();
    }
    String beforePath = ChangesUtil.getProjectRelativePath(myProject, beforeFile);
    String afterPath = ChangesUtil.getProjectRelativePath(myProject, afterFile);
    return new ShelvedBinaryFile(beforePath, afterPath, shelvedPath);
  }

  private void notifyStateChanged() {
    if (!myProject.isDisposed()) {
      myBus.syncPublisher(SHELF_TOPIC).stateChanged(new ChangeEvent(this));
    }
  }

  private File getPatchPath(@NonNls final String commitMessage) {
    File file = myFileProcessor.getBaseIODir();
    if (!file.exists()) {
      //noinspection ResultOfMethodCallIgnored
      file.mkdirs();
    }

    return suggestPatchName(myProject, commitMessage.length() > PatchNameChecker.MAX ? commitMessage.substring(0, PatchNameChecker.MAX) :
                            commitMessage, file, VcsConfiguration.PATCH);
  }

  public static File suggestPatchName(Project project, final String commitMessage, final File file, String extension) {
    @NonNls String defaultPath = PathUtil.suggestFileName(commitMessage);
    if (defaultPath.isEmpty()) {
      defaultPath = "unnamed";
    }
    if (defaultPath.length() > PatchNameChecker.MAX - 10) {
      defaultPath = defaultPath.substring(0, PatchNameChecker.MAX - 10);
    }
    while (true) {
      final File nonexistentFile = FileUtil.findSequentNonexistentFile(file, defaultPath,
                                                           extension == null
                                                           ? VcsConfiguration.getInstance(project).getPatchFileExtension()
                                                           : extension);
      if (nonexistentFile.getName().length() >= PatchNameChecker.MAX) {
        defaultPath = defaultPath.substring(0, defaultPath.length() - 1);
        continue;
      }
      return nonexistentFile;
    }
  }

  public void unshelveChangeList(final ShelvedChangeList changeList, @Nullable final List<ShelvedChange> changes,
                                           @Nullable final List<ShelvedBinaryFile> binaryFiles, final LocalChangeList targetChangeList) {
    unshelveChangeList(changeList, changes, binaryFiles, targetChangeList, true);
  }

  @AsynchronousExecution
  public void unshelveChangeList(final ShelvedChangeList changeList,
                                 @Nullable final List<ShelvedChange> changes,
                                 @Nullable final List<ShelvedBinaryFile> binaryFiles,
                                 @Nullable final LocalChangeList targetChangeList,
                                 boolean showSuccessNotification) {
    final Continuation continuation = Continuation.createForCurrentProgress(myProject, true, "Unshelve changes");
    final GatheringContinuationContext initContext = new GatheringContinuationContext();
    scheduleUnshelveChangeList(changeList, changes, binaryFiles, targetChangeList, showSuccessNotification, initContext, false,
                               false, null, null);
    continuation.run(initContext.getList());
  }

  @AsynchronousExecution
  public void scheduleUnshelveChangeList(final ShelvedChangeList changeList,
                                         @Nullable final List<ShelvedChange> changes,
                                         @Nullable final List<ShelvedBinaryFile> binaryFiles,
                                         @Nullable final LocalChangeList targetChangeList,
                                         final boolean showSuccessNotification,
                                         final ContinuationContext context,
                                         final boolean systemOperation,
                                         final boolean reverse,
                                         final String leftConflictTitle,
                                         final String rightConflictTitle) {
    context.next(new TaskDescriptor("", Where.AWT) {
      @Override
      public void run(ContinuationContext contextInner) {
        final List<FilePatch> remainingPatches = new ArrayList<FilePatch>();

        final CommitContext commitContext = new CommitContext();
        final List<TextFilePatch> textFilePatches;
        try {
          textFilePatches = loadTextPatches(myProject, changeList, changes, remainingPatches, commitContext);
        }
        catch (IOException e) {
          LOG.info(e);
          PatchApplier.showError(myProject, "Cannot load patch(es): " + e.getMessage(), true);
          return;
        }
        catch (PatchSyntaxException e) {
          PatchApplier.showError(myProject, "Cannot load patch(es): " + e.getMessage(), true);
          LOG.info(e);
          return;
        }

        final List<FilePatch> patches = new ArrayList<FilePatch>(textFilePatches);

        final List<ShelvedBinaryFile> remainingBinaries = new ArrayList<ShelvedBinaryFile>();
        final List<ShelvedBinaryFile> binaryFilesToUnshelve = getBinaryFilesToUnshelve(changeList, binaryFiles, remainingBinaries);

        for (final ShelvedBinaryFile shelvedBinaryFile : binaryFilesToUnshelve) {
          patches.add(new ShelvedBinaryFilePatch(shelvedBinaryFile));
        }

        final BinaryPatchApplier binaryPatchApplier = new BinaryPatchApplier();
        final PatchApplier<ShelvedBinaryFilePatch> patchApplier = new PatchApplier<ShelvedBinaryFilePatch>(myProject, myProject.getBaseDir(),
            patches, targetChangeList, binaryPatchApplier, commitContext, reverse, leftConflictTitle, rightConflictTitle);
        patchApplier.setIsSystemOperation(systemOperation);

        // after patch applier part
        contextInner.next(new TaskDescriptor("", Where.AWT) {
          @Override
          public void run(ContinuationContext context) {
            remainingPatches.addAll(patchApplier.getRemainingPatches());

            if (remainingPatches.isEmpty() && remainingBinaries.isEmpty()) {
              recycleChangeList(changeList);
            }
            else {
              saveRemainingPatches(changeList, remainingPatches, remainingBinaries, commitContext);
            }
          }
        });

        patchApplier.scheduleSelf(showSuccessNotification, contextInner, systemOperation);
      }
    });
  }

  private static List<TextFilePatch> loadTextPatches(final Project project, final ShelvedChangeList changeList, final List<ShelvedChange> changes, final List<FilePatch> remainingPatches, final CommitContext commitContext)
      throws IOException, PatchSyntaxException {
    final List<TextFilePatch> textFilePatches = loadPatches(project, changeList.PATH, commitContext);

    if (changes != null) {
      final Iterator<TextFilePatch> iterator = textFilePatches.iterator();
      while (iterator.hasNext()) {
        TextFilePatch patch = iterator.next();
        if (!needUnshelve(patch, changes)) {
          remainingPatches.add(patch);
          iterator.remove();
        }
      }
    }
    return textFilePatches;
  }

  private class BinaryPatchApplier implements CustomBinaryPatchApplier<ShelvedBinaryFilePatch> {
    private final List<FilePatch> myAppliedPatches;

    private BinaryPatchApplier() {
      myAppliedPatches = new ArrayList<FilePatch>();
    }

    @Override
    @NotNull
    public ApplyPatchStatus apply(final List<Pair<VirtualFile, ApplyFilePatchBase<ShelvedBinaryFilePatch>>> patches) throws IOException {
      for (Pair<VirtualFile, ApplyFilePatchBase<ShelvedBinaryFilePatch>> patch : patches) {
        final ShelvedBinaryFilePatch shelvedPatch = patch.getSecond().getPatch();
        unshelveBinaryFile(shelvedPatch.getShelvedBinaryFile(), patch.getFirst());
        myAppliedPatches.add(shelvedPatch);
      }
      return ApplyPatchStatus.SUCCESS;
    }

    @Override
    @NotNull
    public List<FilePatch> getAppliedPatches() {
      return myAppliedPatches;
    }
  }

  private static List<ShelvedBinaryFile> getBinaryFilesToUnshelve(final ShelvedChangeList changeList,
                                                                  final List<ShelvedBinaryFile> binaryFiles,
                                                                  final List<ShelvedBinaryFile> remainingBinaries) {
    if (binaryFiles == null) {
      return new ArrayList<ShelvedBinaryFile>(changeList.getBinaryFiles());
    }
    ArrayList<ShelvedBinaryFile> result = new ArrayList<ShelvedBinaryFile>();
    for(ShelvedBinaryFile file: changeList.getBinaryFiles()) {
      if (binaryFiles.contains(file)) {
        result.add(file);
      } else {
        remainingBinaries.add(file);
      }
    }
    return result;
  }

  @Nullable
  private FilePath unshelveBinaryFile(final ShelvedBinaryFile file, @NotNull final VirtualFile patchTarget) throws IOException {
    final Ref<FilePath> result = new Ref<FilePath>();
    final Ref<IOException> ex = new Ref<IOException>();
    final Ref<VirtualFile> patchedFileRef = new Ref<VirtualFile>();
    final File shelvedFile = file.SHELVED_PATH == null ? null : new File(file.SHELVED_PATH);

    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        try {
          result.set(new FilePathImpl(patchTarget));
          if (shelvedFile == null) {
            patchTarget.delete(this);
          }
          else {
            patchTarget.setBinaryContent(FileUtil.loadFileBytes(shelvedFile));
            patchedFileRef.set(patchTarget);
          }
        }
        catch (IOException e) {
          ex.set(e);
        }
      }
    });
    if (!ex.isNull()) {
      throw ex.get();
    }
    return result.get();
  }

  private static boolean needUnshelve(final FilePatch patch, final List<ShelvedChange> changes) {
    for(ShelvedChange change: changes) {
      if (Comparing.equal(patch.getBeforeName(), change.getBeforePath())) {
        return true;
      }
    }
    return false;
  }

  private static void writePatchesToFile(final Project project,
                                         final String path,
                                         final List<FilePatch> remainingPatches,
                                         CommitContext commitContext) {
    try {
      OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(path), CharsetToolkit.UTF8_CHARSET);
      try {
        UnifiedDiffWriter.write(project, remainingPatches, writer, "\n", commitContext);
      }
      finally {
        writer.close();
      }
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  void saveRemainingPatches(final ShelvedChangeList changeList, final List<FilePatch> remainingPatches,
                            final List<ShelvedBinaryFile> remainingBinaries, CommitContext commitContext) {
    final File newPath = getPatchPath(changeList.DESCRIPTION);
    try {
      FileUtil.copy(new File(changeList.PATH), newPath);
    }
    catch (IOException e) {
      // do not delete if cannot recycle
      return;
    }
    final ShelvedChangeList listCopy = new ShelvedChangeList(newPath.getAbsolutePath(), changeList.DESCRIPTION,
                                                             new ArrayList<ShelvedBinaryFile>(changeList.getBinaryFiles()));
    listCopy.DATE = changeList.DATE == null ? null : new Date(changeList.DATE.getTime());

    writePatchesToFile(myProject, changeList.PATH, remainingPatches, commitContext);

    changeList.getBinaryFiles().retainAll(remainingBinaries);
    changeList.clearLoadedChanges();
    recycleChangeList(listCopy, changeList);
    notifyStateChanged();
  }

  public void restoreList(final ShelvedChangeList changeList) {
    myShelvedChangeLists.add(changeList);
    myRecycledShelvedChangeLists.remove(changeList);
    changeList.setRecycled(false);
    notifyStateChanged();
  }

  public List<ShelvedChangeList> getRecycledShelvedChangeLists() {
    return myRecycledShelvedChangeLists;
  }

  public void clearRecycled() {
    for (ShelvedChangeList list : myRecycledShelvedChangeLists) {
      deleteListImpl(list);
    }
    myRecycledShelvedChangeLists.clear();
    notifyStateChanged();
  }

  private void recycleChangeList(final ShelvedChangeList listCopy, final ShelvedChangeList newList) {
    if (newList != null) {
      for (Iterator<ShelvedBinaryFile> shelvedChangeListIterator = listCopy.getBinaryFiles().iterator();
           shelvedChangeListIterator.hasNext();) {
        final ShelvedBinaryFile binaryFile = shelvedChangeListIterator.next();
        for (ShelvedBinaryFile newBinary : newList.getBinaryFiles()) {
          if (Comparing.equal(newBinary.BEFORE_PATH, binaryFile.BEFORE_PATH)
              && Comparing.equal(newBinary.AFTER_PATH, binaryFile.AFTER_PATH)) {
            shelvedChangeListIterator.remove();
          }
        }
      }
      for (Iterator<ShelvedChange> iterator = listCopy.getChanges(myProject).iterator(); iterator.hasNext();) {
        final ShelvedChange change = iterator.next();
        for (ShelvedChange newChange : newList.getChanges(myProject)) {
          if (Comparing.equal(change.getBeforePath(), newChange.getBeforePath()) &&
              Comparing.equal(change.getAfterPath(), newChange.getAfterPath())) {
            iterator.remove();
          }
        }
      }

      // needed only if partial unshelve
      try {
        final CommitContext commitContext = new CommitContext();
        final List<FilePatch> patches = new ArrayList<FilePatch>();
        for (ShelvedChange change : listCopy.getChanges(myProject)) {
          patches.add(change.loadFilePatch(myProject, commitContext));
        }
        writePatchesToFile(myProject, listCopy.PATH, patches, commitContext);
      }
      catch (IOException e) {
        LOG.info(e);
        // left file as is
      }
      catch (PatchSyntaxException e) {
        LOG.info(e);
        // left file as is
      }
    }

    if (! listCopy.getBinaryFiles().isEmpty() || ! listCopy.getChanges(myProject).isEmpty()) {
      listCopy.setRecycled(true);
      myRecycledShelvedChangeLists.add(listCopy);
      notifyStateChanged();
    }
  }

  private void recycleChangeList(final ShelvedChangeList changeList) {
    recycleChangeList(changeList, null);
    myShelvedChangeLists.remove(changeList);
    notifyStateChanged();
  }

  public void deleteChangeList(final ShelvedChangeList changeList) {
    deleteListImpl(changeList);
    if (! changeList.isRecycled()) {
      myShelvedChangeLists.remove(changeList);
    } else {
      myRecycledShelvedChangeLists.remove(changeList);
    }
    notifyStateChanged();
  }

  private void deleteListImpl(final ShelvedChangeList changeList) {
    File file = new File(changeList.PATH);
    myFileProcessor.delete(file.getName());

    for(ShelvedBinaryFile binaryFile: changeList.getBinaryFiles()) {
      final String path = binaryFile.SHELVED_PATH;
      if (path != null) {
        File binFile = new File(path);
        myFileProcessor.delete(binFile.getName());
      }
    }
  }

  public void renameChangeList(final ShelvedChangeList changeList, final String newName) {
    changeList.DESCRIPTION = newName;
    notifyStateChanged();
  }

  // todo problem: control usage
  public static List<TextFilePatch> loadPatches(Project project, final String patchPath, CommitContext commitContext) throws IOException, PatchSyntaxException {
    char[] text = FileUtil.loadFileText(new File(patchPath), CharsetToolkit.UTF8);
    PatchReader reader = new PatchReader(new CharArrayCharSequence(text));
    final List<TextFilePatch> textFilePatches = reader.readAllPatches();
    final TransparentlyFailedValueI<Map<String, Map<String, CharSequence>>, PatchSyntaxException> additionalInfo = reader.getAdditionalInfo(
      null);
    ApplyPatchDefaultExecutor.applyAdditionalInfoBefore(project, additionalInfo, commitContext);
    return textFilePatches;
  }

  public static class ShelvedBinaryFilePatch extends FilePatch {
    private final ShelvedBinaryFile myShelvedBinaryFile;

    public ShelvedBinaryFilePatch(final ShelvedBinaryFile shelvedBinaryFile) {
      myShelvedBinaryFile = shelvedBinaryFile;
      setBeforeName(myShelvedBinaryFile.BEFORE_PATH);
      setAfterName(myShelvedBinaryFile.AFTER_PATH);
    }

    @Override
    public String getBeforeFileName() {
      String[] pathNameComponents = myShelvedBinaryFile.BEFORE_PATH.replace(File.separatorChar, '/').split("/");
      return pathNameComponents [pathNameComponents.length-1];
    }

    @Override
    public String getAfterFileName() {
      String[] pathNameComponents = myShelvedBinaryFile.AFTER_PATH.replace(File.separatorChar, '/').split("/");
      return pathNameComponents [pathNameComponents.length-1];
    }

    @Override
    public boolean isNewFile() {
      return myShelvedBinaryFile.BEFORE_PATH == null;
    }
    @Override
    public boolean isDeletedFile() {
      return myShelvedBinaryFile.AFTER_PATH == null;
    }

    public ShelvedBinaryFile getShelvedBinaryFile() {
      return myShelvedBinaryFile;
    }
  }

  public boolean isShowRecycled() {
    return myShowRecycled;
  }

  public void setShowRecycled(final boolean showRecycled) {
    myShowRecycled = showRecycled;
    notifyStateChanged();
  }
}
