/*
 * Copyright 2000-2016 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.codeInspection.ex;

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.lang.InspectionExtensionsFactory;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author cdr
 */
public class EditInspectionToolsSettingsInSuppressedPlaceIntention implements IntentionAction {
  private String myId;
  private String myDisplayName;

  @Override
  @NotNull
  public String getFamilyName() {
    return InspectionsBundle.message("edit.options.of.reporter.inspection.family");
  }

  @Override
  @NotNull
  public String getText() {
    return InspectionsBundle.message("edit.inspection.options", myDisplayName);
  }

  @Nullable
  private static String getSuppressedId(Editor editor, PsiFile file) {
    int offset = editor.getCaretModel().getOffset();
    PsiElement element = file.findElementAt(offset);
    while (element != null && !(element instanceof PsiFile)) {
      for (InspectionExtensionsFactory factory : Extensions.getExtensions(InspectionExtensionsFactory.EP_NAME)) {
        final String suppressedIds = factory.getSuppressedInspectionIdsIn(element);
        if (suppressedIds != null) {
          for (String id : StringUtil.split(suppressedIds, ",")) {
            if (isCaretOnSuppressedId(file, offset, id)) {
              return id;
            }
          }
        }
      }
      element = element.getParent();
    }
    return null;
  }

  private static boolean isCaretOnSuppressedId(PsiFile file, int caretOffset, String suppressedId) {
    CharSequence fileText = file.getViewProvider().getContents();
    CharSequence vicinity = fileText.subSequence(caretOffset - suppressedId.length(), caretOffset + suppressedId.length());
    return StringUtil.indexOf(vicinity, suppressedId) >= 0;
  }

  @Override
  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
    myId = getSuppressedId(editor, file);
    if (myId != null) {
      InspectionToolWrapper toolWrapper = getTool(project, file);
      if (toolWrapper == null) return false;
      myDisplayName = toolWrapper.getDisplayName();
    }
    return myId != null;
  }

  @Nullable
  private InspectionToolWrapper getTool(final Project project, final PsiFile file) {
    final InspectionProjectProfileManager projectProfileManager = InspectionProjectProfileManager.getInstance(project);
    final InspectionProfileImpl inspectionProfile = (InspectionProfileImpl)projectProfileManager.getCurrentProfile();
    return inspectionProfile.getToolById(myId, file);
  }

  @Override
  public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
    InspectionToolWrapper toolWrapper = getTool(project, file);
    if (toolWrapper == null) return;
    final InspectionProjectProfileManager projectProfileManager = InspectionProjectProfileManager.getInstance(project);
    final InspectionProfileImpl inspectionProfile = (InspectionProfileImpl)projectProfileManager.getCurrentProfile();
    EditInspectionToolsSettingsAction.editToolSettings(project, inspectionProfile, false, toolWrapper.getShortName());
  }

  @Override
  public boolean startInWriteAction() {
    return false;
  }
}

@@ -2671,53 +2671,32 @@
     
-CharSequence vicinity = fileText.subSequence(
+int start = Math.max(0, 
 care
@@ -2726,18 +2726,42 @@
 length()
-, 
+);%0A    int end = Math.min(
 caretOff
@@ -2783,24 +2783,43 @@
 dId.length()
+, fileText.length()
 );%0A    retur
@@ -2843,16 +2843,40 @@
 xOf(
-vicinity
+fileText.subSequence(start, end)
 , su

fix EditInspectionToolsSettingsInSuppressedPlaceIntention IOOBE