/*
 * Copyright 2000-2011 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.
 */
package git4idea.update;

import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.changes.ui.ChangeListViewerDialog;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import git4idea.GitUtil;
import git4idea.branch.GitBranchPair;
import git4idea.commands.*;
import git4idea.merge.GitConflictResolver;
import git4idea.merge.GitMerger;
import git4idea.repo.GitRepository;
import git4idea.util.GitUIUtil;
import git4idea.util.UntrackedFilesNotifier;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Handles <code>git pull</code> via merge.
 */
public class GitMergeUpdater extends GitUpdater {
  private static final Logger LOG = Logger.getInstance(GitMergeUpdater.class);

  private final ChangeListManager myChangeListManager;

  public GitMergeUpdater(Project project, @NotNull Git git,
                         VirtualFile root,
                         final Map<VirtualFile, GitBranchPair> trackedBranches,
                         ProgressIndicator progressIndicator,
                         UpdatedFiles updatedFiles) {
    super(project, git, root, trackedBranches, progressIndicator, updatedFiles);
    myChangeListManager = ChangeListManager.getInstance(myProject);
  }

  @Override
  @NotNull
  protected GitUpdateResult doUpdate() {
    LOG.info("doUpdate ");
    final GitMerger merger = new GitMerger(myProject);
    final GitLineHandler mergeHandler = new GitLineHandler(myProject, myRoot, GitCommand.MERGE);
    mergeHandler.addParameters("--no-stat", "-v");
    mergeHandler.addParameters(myTrackedBranches.get(myRoot).getDest().getName());

    final MergeLineListener mergeLineListener = new MergeLineListener();
    mergeHandler.addLineListener(mergeLineListener);
    GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(myRoot);
    mergeHandler.addLineListener(untrackedFilesDetector);

    String progressTitle = makeProgressTitle("Merging");
    final GitTask mergeTask = new GitTask(myProject, mergeHandler, progressTitle);
    mergeTask.setProgressIndicator(myProgressIndicator);
    mergeTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
    final AtomicReference<GitUpdateResult> updateResult = new AtomicReference<GitUpdateResult>();
    final AtomicBoolean failure = new AtomicBoolean();
    mergeTask.executeInBackground(true, new GitTaskResultHandlerAdapter() {
      @Override protected void onSuccess() {
        updateResult.set(GitUpdateResult.SUCCESS);
      }

      @Override protected void onCancel() {
        cancel();
        updateResult.set(GitUpdateResult.CANCEL);
      }

      @Override protected void onFailure() {
        failure.set(true);
      }
    });

    if (failure.get()) {
      updateResult.set(handleMergeFailure(mergeLineListener, untrackedFilesDetector, merger, mergeHandler));
    }
    return updateResult.get();
  }

  @NotNull
  private GitUpdateResult handleMergeFailure(MergeLineListener mergeLineListener,
                                             GitMessageWithFilesDetector untrackedFilesWouldBeOverwrittenByMergeDetector,
                                             final GitMerger merger,
                                             GitLineHandler mergeHandler) {
    final MergeError error = mergeLineListener.getMergeError();
    LOG.info("merge error: " + error);
    if (error == MergeError.CONFLICT) {
      LOG.info("Conflict detected");
      final boolean allMerged =
        new MyConflictResolver(myProject, myGit, merger, myRoot).merge();
      return allMerged ? GitUpdateResult.SUCCESS_WITH_RESOLVED_CONFLICTS : GitUpdateResult.INCOMPLETE;
    }
    else if (error == MergeError.LOCAL_CHANGES) {
      LOG.info("Local changes would be overwritten by merge");
      final List<FilePath> paths = getFilesOverwrittenByMerge(mergeLineListener.getOutput());
      final Collection<Change> changes = getLocalChangesFilteredByFiles(paths);
      UIUtil.invokeAndWaitIfNeeded(new Runnable() {
        @Override
        public void run() {
          ChangeListViewerDialog dialog = new ChangeListViewerDialog(myProject, changes, false) {
            @Override protected String getDescription() {
              return "Your local changes to the following files would be overwritten by merge.<br/>" +
                                "Please, commit your changes or stash them before you can merge.";
            }
          };
          dialog.show();
        }
      });
      return GitUpdateResult.ERROR;
    }
    else if (untrackedFilesWouldBeOverwrittenByMergeDetector.wasMessageDetected()) {
      LOG.info("handleMergeFailure: untracked files would be overwritten by merge");
      UntrackedFilesNotifier.notifyUntrackedFilesOverwrittenBy(myProject, myRoot,
                                                               untrackedFilesWouldBeOverwrittenByMergeDetector.getRelativeFilePaths(),
                                                               "merge", null);
      return GitUpdateResult.ERROR;
    }
    else {
      String errors = GitUIUtil.stringifyErrors(mergeHandler.errors());
      LOG.info("Unknown error: " + errors);
      GitUIUtil.notifyImportantError(myProject, "Error merging", errors);
      return GitUpdateResult.ERROR;
    }
  }

  @Override
  public boolean isSaveNeeded() {
    try {
      if (GitUtil.hasLocalChanges(true, myProject, myRoot)) {
        return true;
      }
    }
    catch (VcsException e) {
      LOG.info("isSaveNeeded failed to check staging area", e);
      return true;
    }

    // git log --name-status master..origin/master
    GitBranchPair gitBranchPair = myTrackedBranches.get(myRoot);
    String currentBranch = gitBranchPair.getBranch().getName();
    String remoteBranch = gitBranchPair.getDest().getName();
    try {
      GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(myRoot);
      if (repository == null) {
        LOG.error("Repository is null for root " + myRoot);
        return true; // fail safe
      }
      final Collection<String> remotelyChanged = GitUtil.getPathsDiffBetweenRefs(ServiceManager.getService(Git.class), repository,
                                                                                 currentBranch, remoteBranch);
      final List<File> locallyChanged = myChangeListManager.getAffectedPaths();
      for (final File localPath : locallyChanged) {
        if (ContainerUtil.exists(remotelyChanged, new Condition<String>() {
          @Override
          public boolean value(String remotelyChangedPath) {
            return FileUtil.pathsEqual(localPath.getPath(), remotelyChangedPath);
          }
        })) {
          // found a file which was changed locally and remotely => need to save
          return true;
        }
      }
      return false;
    } catch (VcsException e) {
      LOG.info("failed to get remotely changed files for " + currentBranch + ".." + remoteBranch, e);
      return true; // fail safe
    }
  }

  private void cancel() {
    try {
      GitSimpleHandler h = new GitSimpleHandler(myProject, myRoot, GitCommand.RESET);
      h.addParameters("--merge");
      h.run();
    } catch (VcsException e) {
      LOG.info("cancel git reset --merge", e);
      GitUIUtil.notifyImportantError(myProject, "Couldn't reset merge", e.getLocalizedMessage());
    }
  }

  // parses the output of merge conflict returning files which would be overwritten by merge. These files will be stashed.
  private List<FilePath> getFilesOverwrittenByMerge(@NotNull List<String> mergeOutput) {
    final List<FilePath> paths = new ArrayList<FilePath>();
    for  (String line : mergeOutput) {
      if (StringUtil.isEmptyOrSpaces(line)) {
        continue;
      }
      if (line.contains("Please, commit your changes or stash them before you can merge")) {
        break;
      }
      line = line.trim();

      final String path;
      try {
        path = myRoot.getPath() + "/" + GitUtil.unescapePath(line);
        final File file = new File(path);
        if (file.exists()) {
          paths.add(new FilePathImpl(file, false));
        }
      } catch (VcsException e) { // just continue
      }
    }
    return paths;
  }

  private Collection<Change> getLocalChangesFilteredByFiles(List<FilePath> paths) {
    final Collection<Change> changes = new HashSet<Change>();
    for(LocalChangeList list : myChangeListManager.getChangeLists()) {
      for (Change change : list.getChanges()) {
        final ContentRevision afterRevision = change.getAfterRevision();
        final ContentRevision beforeRevision = change.getBeforeRevision();
        if ((afterRevision != null && paths.contains(afterRevision.getFile())) || (beforeRevision != null && paths.contains(beforeRevision.getFile()))) {
          changes.add(change);
        }
      }
    }
    return changes;
  }

  @Override
  public String toString() {
    return "Merge updater";
  }

  private enum MergeError {
    CONFLICT,
    LOCAL_CHANGES,
    OTHER
  }

  private static class MergeLineListener extends GitLineHandlerAdapter {
    private MergeError myMergeError;
    private List<String> myOutput = new ArrayList<String>();
    private boolean myLocalChangesError = false;

    @Override
    public void onLineAvailable(String line, Key outputType) {
      if (myLocalChangesError) {
        myOutput.add(line);
      } else if (line.contains("Automatic merge failed; fix conflicts and then commit the result")) {
        myMergeError = MergeError.CONFLICT;
      } else if (line.contains("Your local changes to the following files would be overwritten by merge")) {
        myMergeError = MergeError.LOCAL_CHANGES;
        myLocalChangesError = true;
      }
    }

    public MergeError getMergeError() {
      return myMergeError;
    }

    public List<String> getOutput() {
      return myOutput;
    }
  }

  private static class MyConflictResolver extends GitConflictResolver {
    private final GitMerger myMerger;
    private final VirtualFile myRoot;

    public MyConflictResolver(Project project, @NotNull Git git, GitMerger merger, VirtualFile root) {
      super(project, git, ServiceManager.getService(git4idea.GitPlatformFacade.class), Collections.singleton(root), makeParams());
      myMerger = merger;
      myRoot = root;
    }
    
    private static Params makeParams() {
      Params params = new Params();
      params.setErrorNotificationTitle("Can't complete update");
      params.setMergeDescription("Merge conflicts detected. Resolve them before continuing update.");
      return params;
    }

    @Override protected boolean proceedIfNothingToMerge() throws VcsException {
      myMerger.mergeCommit(myRoot);
      return true;
    }

    @Override protected boolean proceedAfterAllMerged() throws VcsException {
      myMerger.mergeCommit(myRoot);
      return true;
    }
  }
}
