/*
 * Copyright 2000-2012 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;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.intellij.mock.MockVirtualFile;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
import com.intellij.testFramework.vcs.MockChangeListManager;
import com.intellij.testFramework.vcs.MockContentRevision;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsLogObjectsFactory;
import com.intellij.vcs.log.impl.HashImpl;
import cucumber.annotation.en.And;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import git4idea.cherrypick.GitCherryPicker;
import git4idea.config.GitVersionSpecialty;
import git4idea.test.MockVcsHelper;

import java.util.*;

import static com.intellij.openapi.vcs.Executor.echo;
import static git4idea.GitCucumberWorld.*;
import static git4idea.test.GitExecutor.git;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertFalse;

/**
 * @author Kirill Likhodedov
 */

public class GitCherryPickStepdefs {

  @Given("^(enabled|disabled) auto-commit in the settings$")
  public void auto_commit_in_the_settings(String state) {
    boolean enabled = state.equals("enabled");
    myPlatformFacade.getSettings(myProject).setAutoCommitOnCherryPick(enabled);
  }

  @When("^I cherry-pick the commit (\\w+)$")
  public void I_cherry_pick_the_commit(String hash) {
    cherryPick(hash);
  }

  @When("^I cherry-pick commits (.+) and (\\w+)$")
  public void I_cherry_pick_commits(String severalCommits, String hash2) throws Throwable {

    String[] hashes = severalCommits.split(",");
    String[] allHashes = new String[hashes.length + 1];
    for (int i = 0; i < allHashes.length - 1; i++) {
      allHashes[i] = hashes[i].trim();
    }
    allHashes[allHashes.length - 1] = hash2;
    cherryPick(allHashes);
  }

  @When("^I cherry-pick the commit (\\w+) and( don't)? resolve conflicts$")
  public void I_cherry_pick_the_commit_and_resolve_conflicts(String hash, String negation) throws Throwable {
    if (negation == null) {
      resolveConflictsInFuture();
    }
    cherryPick(hash);
  }

  private static void resolveConflictsInFuture() {
    myVcsHelper.registerHandler(new MockVcsHelper.MergeHandler() {
      @Override
      public void showMergeDialog() {
        git("add -u .");
      }
    });
  }

  private static void commitInFuture(final int times) {
    myVcsHelper.registerHandler(new MockVcsHelper.CommitHandler() {

      private int myCommitRequests;

      @Override
      public boolean commit(String commitMessage) {
        if (myCommitRequests >= times) {
          return false;
        }
        myCommitRequests++;
        git(String.format("commit -am '%s'", commitMessage));
        return true;
      }
    });
  }

  private static void commitInFuture() {
    commitInFuture(Integer.MAX_VALUE);
  }

  @When("^I cherry-pick the commit (.+), resolve conflicts and( don't)? commit$")
  public void I_cherry_pick_the_commit_resolve_conflicts_and_commit(String hash, String negation) throws Throwable {
    resolveConflictsInFuture();
    if (negation == null) {
      commitInFuture();
    }
    cherryPick(hash);
  }

  @When("^I cherry-pick the commit (\\w+) and( don't)? commit$")
  public void I_cherry_pick_the_commit_hash_and_commit(String hash, String negation) throws Throwable {
    if (negation == null) {
      commitInFuture();
    }
    cherryPick(hash);
  }

  @When("^I cherry-pick commits (.+) and commit both of them$")
  public void I_cherry_pick_commits_and_commit_both_of_them(String listOfHashes) throws Throwable {
    commitInFuture();
    cherryPick(GeneralStepdefs.splitByComma(listOfHashes));
  }

  @When("^I cherry-pick commits (.+), but commit only the first one$")
  public void I_cherry_pick_commits_but_commit_only_the_first_one(String listOfHashes) throws Throwable {
    commitInFuture(1);
    cherryPick(GeneralStepdefs.splitByComma(listOfHashes));
  }

  @Then("^the last commit is$")
  public void the_last_commit_is(String message) throws Throwable {
    git_log_should_return(1, message);
  }

  @Then("^the last commit is (.+)$")
  public void the_last_commit_is_hash(String hash) throws Throwable {
    assertEquals("The last commit hash doesn't match", virtualCommits.replaceVirtualHashes(hash), git("log -1 --pretty=%h"));
  }

  @Then("^`git log -(\\d+)` should return$")
  public void git_log_should_return(int commitNum, String messages) throws Throwable {
    List<String> expectedMessages = Arrays.asList(messages.split("-----"));

    final String RECORD_SEPARATOR = "@";
    boolean fullBody = GitVersionSpecialty.STARTED_USING_RAW_BODY_IN_FORMAT.existsIn(myVcs.getVersion());
    String data = fullBody ? "%B" : "%s%b";
    String output = git("log -%s --pretty=%s%s", String.valueOf(commitNum), data, RECORD_SEPARATOR);
    List<String> actualMessages = Arrays.asList(output.split(RECORD_SEPARATOR));

    for (int i = 0; i < expectedMessages.size(); i++) {
      String expectedMessage = StringUtil.convertLineSeparators(expectedMessages.get(i).trim());
      String actualMessage = StringUtil.convertLineSeparators(actualMessages.get(i).trim());
      if (!fullBody) {
        // the subject (%s) contains both "fix #1" and "cherry-picked from <hash>" in a single line
        // so let's compare without taking line breaks and spaces into consideration
        expectedMessage = expectedMessage.replace("\n", "").replace(" ", "");
        actualMessage = actualMessage.replace("\n", "").replace(" ", "");
      }
      expectedMessage = virtualCommits.replaceVirtualHashes(expectedMessage);
      assertEquals("Commit doesn't match", expectedMessage, trimHash(actualMessage));
    }
  }

  @And("^no new changelists are created$")
  public void no_new_changelists_are_created() {
    assertOnlyDefaultChangelist();
  }

  @Given("^(.+) is locally modified:$")
  public void is_locally_modified(String filename, String content) {
    echo(filename, content);
  }

  String trimHash(String commitMessage) {
    return commitMessage.replaceAll("([a-fA-F0-9]{7})[a-fA-F0-9]{33}", "$1");
  }

  @Then("^nothing is committed$")
  public void nothing_is_committed() throws Throwable {
    working_tree_is_dirty();
  }

  @And("^working tree is dirty$")
  public void working_tree_is_dirty() throws Throwable {
    assertFalse("Working tree is unexpectedly clean", git("diff").trim().isEmpty() && git("diff --cached").trim().isEmpty());
  }

  @Then("^merge dialog should be shown$")
  public void merge_dialog_should_be_shown() throws Throwable {
    assertTrue("Merge dialog was not shown", myVcsHelper.mergeDialogWasShown());
  }

  @Then("^commit dialog should be shown$")
  public void commit_dialog_should_be_shown() throws Throwable {
    assertTrue("Commit dialog was not shown", myVcsHelper.commitDialogWasShown());
  }

  @Then("^active changelist is '(.+)'$")
  public void active_changelist_is(String name) throws Throwable {
    assertActiveChangeList(virtualCommits.replaceVirtualHashes(name));
  }

  private static void assertOnlyDefaultChangelist() {
    String DEFAULT = MockChangeListManager.DEFAULT_CHANGE_LIST_NAME;
    assertChangeLists(Collections.singleton(DEFAULT), DEFAULT);
  }

  private static void assertChangeLists(Collection<String> changeLists, String activeChangelist) {
    List<LocalChangeList> lists = myChangeListManager.getChangeLists();
    Collection<String> listNames = Collections2.transform(lists, new Function<LocalChangeList, String>() {
      @Override
      public String apply(LocalChangeList input) {
        return input.getName();
      }
    });
    assertEquals("Change lists are different", new ArrayList<String>(changeLists), new ArrayList<String>(listNames));
    assertActiveChangeList(activeChangelist);
  }

  private static void assertActiveChangeList(String name) {
    assertEquals("Wrong active changelist", name, myChangeListManager.getDefaultChangeList().getName());
  }

  private static void cherryPick(List<String> virtualHashes) {
    List<VcsFullCommitDetails> commits = ContainerUtil.newArrayList();
    for (String virtualHash : virtualHashes) {
      commits.add(createMockCommit(virtualHash));
    }
    new GitCherryPicker(myProject, myGit, myPlatformFacade, mySettings.isAutoCommitOnCherryPick())
      .cherryPick(Collections.singletonMap(myRepository, commits));
  }

  private static void cherryPick(String... virtualHashes) {
    cherryPick(Arrays.asList(virtualHashes));
  }

  private static VcsFullCommitDetails createMockCommit(String virtualHash) {
    CommitDetails realCommit = virtualCommits.getRealCommit(virtualHash);
    return mockCommit(realCommit.getHash(), realCommit.getMessage());
  }

  private static VcsFullCommitDetails mockCommit(String hash, String message) {
    final List<Change> changes = new ArrayList<Change>();
    changes.add(new Change(null, new MockContentRevision(new FilePathImpl(new MockVirtualFile("name")), VcsRevisionNumber.NULL)));
    return ServiceManager.getService(myProject, VcsLogObjectsFactory.class).createFullDetails(
      HashImpl.build(hash), Collections.<Hash>emptyList(), 0, NullVirtualFile.INSTANCE, message, "John Smith", "john@mail.com", message,
      "John Smith", "john@mail.com", 0, new ThrowableComputable<Collection<Change>, Exception>() {
        @Override
        public Collection<Change> compute() throws Exception {
          return changes;
        }
      }
    );
  }

}