/*
 * Copyright 2000-2013 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 org.jetbrains.idea.svn.dialogs;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.WorkingCopyFormat;
import org.jetbrains.idea.svn.api.ClientFactory;
import org.jetbrains.idea.svn.api.EventAction;
import org.jetbrains.idea.svn.api.ProgressEvent;
import org.jetbrains.idea.svn.api.ProgressTracker;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNException;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SvnFormatWorker extends Task.Backgroundable {

  private static final Logger LOG = Logger.getInstance(SvnFormatWorker.class);

  private List<Throwable> myExceptions;
  private final Project myProject;
  @NotNull private final WorkingCopyFormat myNewFormat;
  private final List<WCInfo> myWcInfos;
  private List<LocalChangeList> myBeforeChangeLists;
  private final SvnVcs myVcs;

  public SvnFormatWorker(final Project project, @NotNull final WorkingCopyFormat newFormat, final List<WCInfo> wcInfos) {
    super(project, SvnBundle.message("action.change.wcopy.format.task.title"), false, DEAF);
    myProject = project;
    myNewFormat = newFormat;
    myExceptions = new ArrayList<Throwable>();
    myWcInfos = wcInfos;
    myVcs = SvnVcs.getInstance(myProject);
  }

  public SvnFormatWorker(final Project project, @NotNull final WorkingCopyFormat newFormat, final WCInfo wcInfo) {
    this(project, newFormat, Collections.singletonList(wcInfo));
  }

  public boolean haveStuffToConvert() {
    return ! myWcInfos.isEmpty();
  }

  @Override
  public void onCancel() {
    onSuccess();
  }

  @Override
  public void onSuccess() {
    if (myProject.isDisposed()) {
      return;
    }

    if (! myExceptions.isEmpty()) {
      final List<String> messages = new ArrayList<String>();
      for (Throwable exception : myExceptions) {
        messages.add(exception.getMessage());
      }
      AbstractVcsHelper.getInstance(myProject)
          .showErrors(Collections.singletonList(new VcsException(messages)), SvnBundle.message("action.change.wcopy.format.task.title"));
    }
  }

  public void run(@NotNull final ProgressIndicator indicator) {
    ProjectLevelVcsManager.getInstanceChecked(myProject).startBackgroundVcsOperation();
    indicator.setIndeterminate(true);
    final boolean supportsChangelists = myNewFormat.supportsChangelists();
    if (supportsChangelists) {
      myBeforeChangeLists = ChangeListManager.getInstance(myProject).getChangeListsCopy();
    }

    try {
      for (WCInfo wcInfo : myWcInfos) {
        File path = new File(wcInfo.getPath());
        if (! wcInfo.isIsWcRoot()) {
          path = SvnUtil.getWorkingCopyRoot(path);
        }
        try {
          String cleanupMessage = SvnBundle.message("action.Subversion.cleanup.progress.text", path.getAbsolutePath());
          String upgradeMessage =
            SvnBundle.message("action.change.wcopy.format.task.progress.text", path.getAbsolutePath(), wcInfo.getFormat(), myNewFormat);
          ProgressTracker handler = createUpgradeHandler(indicator, cleanupMessage, upgradeMessage);

          getFactory(path, myNewFormat).createUpgradeClient().upgrade(path, myNewFormat, handler);
        } catch (Throwable e) {
          myExceptions.add(e);
        }
      }
    }
    finally {
      ProjectLevelVcsManager.getInstance(myProject).stopBackgroundVcsOperation();

      // to map to native
      if (supportsChangelists) {
        SvnVcs.getInstance(myProject).processChangeLists(myBeforeChangeLists);
      }

      ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run();
    }
  }

  @NotNull
  private ClientFactory getFactory(@NotNull File path, @NotNull WorkingCopyFormat format) throws VcsException {
    ClientFactory factory = myVcs.getFactory(path);
    ClientFactory otherFactory = myVcs.getOtherFactory(factory);
    List<WorkingCopyFormat> factoryFormats = factory.createUpgradeClient().getSupportedFormats();
    List<WorkingCopyFormat> otherFactoryFormats = getOtherFactoryFormats(otherFactory);

    return factoryFormats.contains(format) || !otherFactoryFormats.contains(format) ? factory : otherFactory;
  }

  public static List<WorkingCopyFormat> getOtherFactoryFormats(@NotNull ClientFactory otherFactory) {
    List<WorkingCopyFormat> result;

    try {
      result = otherFactory.createUpgradeClient().getSupportedFormats();
    }
    catch (VcsException e) {
      result = ContainerUtil.newArrayList();
      LOG.info("Failed to get upgrade formats from other factory", e);
    }

    return result;
  }

  private static ProgressTracker createUpgradeHandler(@NotNull final ProgressIndicator indicator,
                                                       @NotNull final String cleanupMessage,
                                                       @NotNull final String upgradeMessage) {
    return new ProgressTracker() {
      @Override
      public void consume(ProgressEvent event) throws SVNException {
        if (event.getFile() != null) {
          if (EventAction.UPGRADED_PATH.equals(event.getAction())) {
            indicator.setText2("Upgraded path " + VcsUtil.getPathForProgressPresentation(event.getFile()));
          }
          // fake event indicating cleanup start
          if (EventAction.UPDATE_STARTED.equals(event.getAction())) {
            indicator.setText(cleanupMessage);
          }
          // fake event indicating upgrade start
          if (EventAction.UPDATE_COMPLETED.equals(event.getAction())) {
            indicator.setText(upgradeMessage);
          }
        }
      }

      @Override
      public void checkCancelled() throws SVNCancelException {
        indicator.checkCanceled();
      }
    };
  }
}
