/*
 * 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.vcs.actions;

import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.ex.LineStatusTracker;
import com.intellij.openapi.vcs.ex.LineStatusTrackerDrawing;
import com.intellij.openapi.vcs.ex.Range;
import com.intellij.openapi.vcs.impl.LineStatusTrackerManager;
import org.jetbrains.annotations.NotNull;

/**
 * author: lesya
 */
public abstract class ShowChangeMarkerAction extends AbstractVcsAction {
  protected final ChangeMarkerContext myChangeMarkerContext;
  

  protected abstract Range extractRange(LineStatusTracker lineStatusTracker, int line, Editor editor);

  public ShowChangeMarkerAction(final Range range, final LineStatusTracker lineStatusTracker, final Editor editor) {
    myChangeMarkerContext = new ChangeMarkerContext() {
      @Override
      public Range getRange(VcsContext dataContext) {
        return range;
      }

      @Override
      public LineStatusTracker getLineStatusTracker(VcsContext dataContext) {
        return lineStatusTracker;
      }

      @Override
      public Editor getEditor(VcsContext dataContext) {
        return editor;
      }
    };
  }

  @Override
  protected boolean forceSyncUpdate(final AnActionEvent e) {
    return true;
  }

  public ShowChangeMarkerAction() {
    myChangeMarkerContext = new ChangeMarkerContext() {
      @Override
      public Range getRange(VcsContext context) {
        Editor editor = getEditor(context);
        if (editor == null) return null;

        LineStatusTracker lineStatusTracker = getLineStatusTracker(context);
        if (lineStatusTracker == null) return null;

        return extractRange(lineStatusTracker, editor.getCaretModel().getLogicalPosition().line, editor);
      }

      @Override
      public LineStatusTracker getLineStatusTracker(VcsContext dataContext) {
        Editor editor = getEditor(dataContext);
        if (editor == null) return null;
        Project project = dataContext.getProject();
        if (project == null) return null;
        return LineStatusTrackerManager.getInstance(project).getLineStatusTracker(editor.getDocument());
      }

      @Override
      public Editor getEditor(VcsContext dataContext) {
        return dataContext.getEditor();
      }
    };
  }

  private boolean isActive(VcsContext context) {
    return myChangeMarkerContext.getRange(context) != null;
  }

  @Override
  protected void update(VcsContext context, Presentation presentation) {
    boolean active = isActive(context);
    presentation.setEnabled(active);
    presentation.setVisible(context.getEditor() != null || ActionPlaces.isToolbarPlace(context.getPlace()));
  }


  @Override
  protected void actionPerformed(@NotNull VcsContext context) {
    Editor editor = myChangeMarkerContext.getEditor(context);
    LineStatusTracker lineStatusTracker = myChangeMarkerContext.getLineStatusTracker(context);
    Range range = myChangeMarkerContext.getRange(context);


    LineStatusTrackerDrawing.moveToRange(range, editor, lineStatusTracker);
  }

  protected interface ChangeMarkerContext {
    Range getRange(VcsContext dataContext);

    LineStatusTracker getLineStatusTracker(VcsContext dataContext);

    Editor getEditor(VcsContext dataContext);
  }
}

@@ -803,16 +803,64 @@
 tation;%0A
+import com.intellij.openapi.diff.impl.DiffUtil;%0A
 import c
@@ -1361,18 +1361,16 @@
 ontext;%0A
-  
 %0A%0A  prot
@@ -3145,24 +3145,86 @@
  context) %7B%0A
+    Editor editor = myChangeMarkerContext.getEditor(context);%0A
     return m
@@ -3265,24 +3265,76 @@
 ext) != null
+ && editor != null && !DiffUtil.isDiffEditor(editor)
 ;%0A  %7D%0A%0A  @Ov
@@ -3518,17 +3518,31 @@
 Visible(
-c
+myChangeMarkerC
 ontext.g
@@ -3550,16 +3550,23 @@
 tEditor(
+context
 ) != nul

disable LST actions inside diff editor