/*
 * 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.
 */
package com.intellij.openapi.diff.impl.incrementalMerge;

import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.diff.DiffContent;
import com.intellij.openapi.diff.DiffRequest;
import com.intellij.openapi.diff.ex.DiffFragment;
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
import com.intellij.openapi.diff.impl.incrementalMerge.ui.MergePanel2;
import com.intellij.openapi.diff.impl.processing.DiffPolicy;
import com.intellij.openapi.diff.impl.string.DiffString;
import com.intellij.openapi.diff.impl.util.ContextLogger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.diff.FilesTooBigForDiffException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class MergeList implements UserDataHolder {

  public static final FragmentSide BRANCH_SIDE = FragmentSide.SIDE2;
  public static final FragmentSide BASE_SIDE = FragmentSide.SIDE1;

  public static final DataKey<MergeList> DATA_KEY = DataKey.create("mergeList");
  public static final Condition<Change> NOT_CONFLICTS = new Condition<Change>() {
    public boolean value(Change change) {
      return !(change instanceof ConflictChange);
    }
  };

  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.MergeList");

  @NotNull private final UserDataHolderBase myDataHolder = new UserDataHolderBase();
  @NotNull private final ChangeList myBaseToLeftChangeList;
  @NotNull private final ChangeList myBaseToRightChangeList;
  @Nullable private final String myErrorMessage;

  private MergeList(@Nullable Project project,
                    @NotNull Document left,
                    @NotNull Document base,
                    @NotNull Document right,
                    @Nullable String errorMessage) {
    myBaseToLeftChangeList = new ChangeList(base, left, project);
    myBaseToRightChangeList = new ChangeList(base, right, project);
    myErrorMessage = errorMessage;
  }

  @NotNull
  public ChangeList getLeftChangeList() {
    return myBaseToLeftChangeList;
  }

  @NotNull
  public ChangeList getRightChangeList() {
    return myBaseToRightChangeList;
  }

  @NotNull
  public static MergeList create(@Nullable Project project, @NotNull Document left, @NotNull Document base, @NotNull Document right) {
    MergeList mergeList;
    String leftText = left.getText();
    String baseText = base.getText();
    String rightText = right.getText();
    @NonNls final Object[] data = {
      "Left\n", leftText,
      "\nBase\n", baseText,
      "\nRight\n", rightText
    };
    ContextLogger logger = new ContextLogger(LOG, new ContextLogger.SimpleContext(data));
    List<MergeFragment> fragmentList;
    try {
      fragmentList = processText(leftText, baseText, rightText, logger);
      mergeList = new MergeList(project, left, base, right, null);
    }
    catch (FilesTooBigForDiffException e) {
      fragmentList = Collections.emptyList();
      mergeList = new MergeList(project, left, base, right, e.getMessage());
    }

    ArrayList<Change> leftChanges = new ArrayList<Change>();
    ArrayList<Change> rightChanges = new ArrayList<Change>();
    for (MergeFragment mergeFragment : fragmentList) {
      TextRange baseRange = mergeFragment.getBase();
      TextRange leftRange = mergeFragment.getLeft();
      TextRange rightRange = mergeFragment.getRight();

      if (compareSubstring(leftText, leftRange, rightText, rightRange)) {
        MergeNoConflict conflict = new MergeNoConflict(baseRange, leftRange, rightRange, mergeList);
        assert conflict.getLeftChange() != null;
        assert conflict.getRightChange() != null;
        leftChanges.add(conflict.getLeftChange());
        rightChanges.add(conflict.getRightChange());
      }
      else if (compareSubstring(baseText, baseRange, leftText, leftRange)) {
        rightChanges.add(SimpleChange.fromRanges(baseRange, rightRange, mergeList.myBaseToRightChangeList));
      }
      else if (compareSubstring(baseText, baseRange, rightText, rightRange)) {
        leftChanges.add(SimpleChange.fromRanges(baseRange, leftRange, mergeList.myBaseToLeftChangeList));
      }
      else {
        MergeConflict conflict = new MergeConflict(baseRange, leftRange, rightRange, mergeList);
        assert conflict.getLeftChange() != null;
        assert conflict.getRightChange() != null;
        leftChanges.add(conflict.getLeftChange());
        rightChanges.add(conflict.getRightChange());
      }
    }
    mergeList.myBaseToLeftChangeList.setChanges(leftChanges);
    mergeList.myBaseToRightChangeList.setChanges(rightChanges);
    return mergeList;
  }

  private static boolean compareSubstring(@NotNull String text1,
                                          @NotNull TextRange range1,
                                          @NotNull String text2,
                                          @NotNull TextRange range2) {
    if (range1.getLength() != range2.getLength()) return false;

    int index1 = range1.getStartOffset();
    int index2 = range2.getStartOffset();
    while (index1 < range1.getEndOffset()) {
      if (text1.charAt(index1) != text2.charAt(index2)) return false;
      index1++;
      index2++;
    }
    return true;
  }

  @NotNull
  private static List<MergeFragment> processText(@NotNull String leftText,
                                                 @NotNull String baseText,
                                                 @NotNull String rightText,
                                                 @NotNull ContextLogger logger) throws FilesTooBigForDiffException {
    DiffFragment[] leftFragments = DiffPolicy.DEFAULT_LINES.buildFragments(DiffString.create(baseText), DiffString.create(leftText));
    DiffFragment[] rightFragments = DiffPolicy.DEFAULT_LINES.buildFragments(DiffString.create(baseText), DiffString.create(rightText));
    int[] leftOffsets = {0, 0};
    int[] rightOffsets = {0, 0};
    int leftIndex = 0;
    int rightIndex = 0;
    MergeBuilder builder = new MergeBuilder(logger);
    while (leftIndex < leftFragments.length || rightIndex < rightFragments.length) {
      FragmentSide side;
      TextRange[] equalRanges = new TextRange[2];
      if (leftOffsets[0] < rightOffsets[0] && leftIndex < leftFragments.length) {
        side = FragmentSide.SIDE1;
        getEqualRanges(leftFragments[leftIndex], leftOffsets, equalRanges);
        leftIndex++;
      } else if (rightIndex < rightFragments.length) {
        side = FragmentSide.SIDE2;
        getEqualRanges(rightFragments[rightIndex], rightOffsets, equalRanges);
        rightIndex++;
      } else break;
      if (equalRanges[0] != null && equalRanges[1] != null) builder.add(equalRanges[0], equalRanges[1], side);
      else logger.assertTrue(equalRanges[0] == null && equalRanges[1] == null);
    }
    return builder.finish(leftText.length(), baseText.length(), rightText.length());
  }

  private static void getEqualRanges(@NotNull DiffFragment fragment, @NotNull int[] leftOffsets, @NotNull TextRange[] equalRanges) {
    int baseLength = getTextLength(fragment.getText1());
    int versionLength = getTextLength(fragment.getText2());
    if (fragment.isEqual()) {
      equalRanges[0] = new TextRange(leftOffsets[0], leftOffsets[0] + baseLength);
      equalRanges[1] = new TextRange(leftOffsets[1], leftOffsets[1] + versionLength);
    } else {
      equalRanges[0] = null;
      equalRanges[1] = null;
    }
    leftOffsets[0] += baseLength;
    leftOffsets[1] += versionLength;
  }

  private static int getTextLength(@Nullable DiffString text1) {
    return text1 != null ? text1.length() : 0;
  }

  public static MergeList create(@NotNull DiffRequest data) {
    DiffContent[] contents = data.getContents();
    return create(data.getProject(), contents[0].getDocument(), contents[1].getDocument(), contents[2].getDocument());
  }

  public void setMarkups(Editor left, Editor base, Editor right) {
    myBaseToLeftChangeList.setMarkup(base, left);
    myBaseToRightChangeList.setMarkup(base, right);
    addActions(FragmentSide.SIDE1);
    addActions(FragmentSide.SIDE2);
  }

  public Iterator<Change> getAllChanges() {
    return ContainerUtil.concatIterators(myBaseToLeftChangeList.getChanges().iterator(), myBaseToRightChangeList.getChanges().iterator());
  }

  public void addListener(ChangeList.Listener listener) {
    myBaseToLeftChangeList.addListener(listener);
    myBaseToRightChangeList.addListener(listener);
  }

  public void removeListener(ChangeList.Listener listener) {
    myBaseToLeftChangeList.removeListener(listener);
    myBaseToRightChangeList.removeListener(listener);
  }

  private void addActions(@NotNull final FragmentSide side) {
    ChangeList changeList = getChanges(side);
    final FragmentSide originalSide = BRANCH_SIDE;
    for (int i = 0; i < changeList.getCount(); i++) {
      final Change change = changeList.getChange(i);
      if (!change.canHasActions(originalSide)) continue;
      AnAction applyAction = new AnAction(DiffBundle.message("merge.dialog.apply.change.action.name"), null, AllIcons.Diff.Arrow) {
        public void actionPerformed(AnActionEvent e) {
          apply(change);
        }
      };
      AnAction ignoreAction = new AnAction(DiffBundle.message("merge.dialog.ignore.change.action.name"), null, AllIcons.Diff.Remove) {
        public void actionPerformed(AnActionEvent e) {
          change.removeFromList();
        }
      };
      change.getChangeSide(originalSide).getHighlighterHolder().setActions(new AnAction[]{applyAction, ignoreAction});
    }
  }

  private static void apply(final Change change) {
    Change.apply(change, BRANCH_SIDE);
  }

  @NotNull
  public ChangeList getChanges(@NotNull final FragmentSide changesSide) {
    if (changesSide == FragmentSide.SIDE1) {
      return myBaseToLeftChangeList;
    }
    else {
      return myBaseToRightChangeList;
    }
  }

  public void removeChanges(@Nullable Change leftChange, @Nullable Change rightChange) {
    if (leftChange != null) {
      myBaseToLeftChangeList.remove(leftChange);
    }
    if (rightChange != null) {
      myBaseToRightChangeList.remove(rightChange);
    }
  }

  public Document getBaseDocument() {
    Document document = myBaseToLeftChangeList.getDocument(BASE_SIDE);
    LOG.assertTrue(document == myBaseToRightChangeList.getDocument(BASE_SIDE));
    return document;
  }

  @Nullable
  public static MergeList fromDataContext(DataContext dataContext) {
    MergeList mergeList = DATA_KEY.getData(dataContext);
    if (mergeList != null) return mergeList;
    MergePanel2 mergePanel = MergePanel2.fromDataContext(dataContext);
    return mergePanel == null ? null : mergePanel.getMergeList();
  }

  public <T> T getUserData(@NotNull Key<T> key) {
    return myDataHolder.getUserData(key);
  }

  public <T> void putUserData(@NotNull Key<T> key, T value) {
    myDataHolder.putUserData(key, value);
  }

  @NotNull
  public FragmentSide getSideOf(@NotNull ChangeList source) {
    if (myBaseToLeftChangeList == source) {
      return FragmentSide.SIDE1;
    }
    else {
      return FragmentSide.SIDE2;
    }
  }

  public void updateMarkup() {
    myBaseToLeftChangeList.updateMarkup();
    myBaseToRightChangeList.updateMarkup();
  }

  @Nullable
  public String getErrorMessage() {
    return myErrorMessage;
  }
}
