package com.intellij.codeInsight.daemon.impl;

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.ProjectJdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author ven
 */
public class AddNoInspectionDocTagAction implements IntentionAction {
  private String myID;
  protected PsiElement myContext;

  public AddNoInspectionDocTagAction(LocalInspectionTool tool, PsiElement context) {
    myID = tool.getID();
    myContext = context;
  }

  public AddNoInspectionDocTagAction(HighlightDisplayKey key, PsiElement context) {
    myID = key.getID();
    myContext = context;
  }

  public AddNoInspectionDocTagAction(String ID, PsiElement context) {
    myID = ID;
    myContext = context;
  }

  @NotNull
  public String getText() {
    PsiDocCommentOwner container = getContainer();

    @NonNls String key = container instanceof PsiClass
                         ? "suppress.inspection.class"
                         : container instanceof PsiMethod
                           ? "suppress.inspection.method"
                           : "suppress.inspection.field";
    return InspectionsBundle.message(key);
  }

  @Nullable protected PsiDocCommentOwner getContainer() {
    if (!(myContext.getContainingFile().getLanguage() instanceof JavaLanguage) || myContext instanceof PsiFile){
      return null;
    }
    PsiElement container = myContext;
    do {
      container = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class);
    }
    while (container instanceof PsiTypeParameter);
    return (PsiDocCommentOwner)container;
  }

  @NotNull
  public String getFamilyName() {
    return InspectionsBundle.message("suppress.inspection.family");
  }

  public boolean isAvailable(Project project, Editor editor, PsiFile file) {
    final Module module = ModuleUtil.findModuleForPsiElement(myContext);
    if (module == null) return false;
    final ProjectJdk jdk = ModuleRootManager.getInstance(module).getJdk();
    if (jdk == null) return false;
    final boolean is_1_5 = jdk.getVersionString().indexOf("1.5") > 0;
    return !(DaemonCodeAnalyzerSettings.getInstance().SUPPRESS_WARNINGS && is_1_5 && LanguageLevel.JDK_1_5.compareTo(PsiUtil.getLanguageLevel(myContext)) <= 0) &&
           myContext.isValid() && myContext.getManager().isInProject(myContext) && getContainer() != null;
  }

  public void invoke(Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
    PsiDocCommentOwner container = getContainer();
    assert container != null;
    final ReadonlyStatusHandler.OperationStatus status = ReadonlyStatusHandler.getInstance(project)
      .ensureFilesWritable(container.getContainingFile().getVirtualFile());
    if (status.hasReadonlyFiles()) return;
    PsiDocComment docComment = container.getDocComment();
    PsiManager manager = myContext.getManager();
    if (docComment == null) {
      String commentText = "/** @" + GlobalInspectionContextImpl.SUPPRESS_INSPECTIONS_TAG_NAME + " "+ myID + "*/";
      docComment = manager.getElementFactory().createDocCommentFromText(commentText, null);
      PsiElement firstChild = container.getFirstChild();
      container.addBefore(docComment, firstChild);
      return;
    }

    PsiDocTag noInspectionTag = docComment.findTagByName(GlobalInspectionContextImpl.SUPPRESS_INSPECTIONS_TAG_NAME);
    if (noInspectionTag != null) {
      String tagText = "@" + GlobalInspectionContextImpl.SUPPRESS_INSPECTIONS_TAG_NAME + " "
                       + noInspectionTag.getValueElement().getText() + ","+ myID;
      noInspectionTag.replace(manager.getElementFactory().createDocTagFromText(tagText, null));
    } else {
      String tagText = "@" + GlobalInspectionContextImpl.SUPPRESS_INSPECTIONS_TAG_NAME + " " + myID;
      docComment.add(manager.getElementFactory().createDocTagFromText(tagText, null));
    }
  }

  public boolean startInWriteAction() {
    return true;
  }
}

@@ -857,16 +857,81 @@
 .psi.*;%0A
+import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;%0A
 import c
@@ -3079,32 +3079,89 @@
 ) return false;%0A
+    final String versionString = jdk.getVersionString();%0A
     final boolea
@@ -3171,24 +3171,17 @@
 s_1_5 = 
-jdk.getV
+v
 ersionSt
@@ -3184,18 +3184,16 @@
 onString
-()
 .indexOf
@@ -3207,23 +3207,82 @@
  %3E 0
-;
+ %7C%7C
 %0A    
-return !(
+                       versionString.indexOf(%221.6%22) %3E 0;%0A    if (!
 Daem
@@ -3340,20 +3340,29 @@
 NGS 
-&& 
+%7C%7C%0A        !
 is_1_5 
-&&
+%7C%7C
  Lan
@@ -3431,16 +3431,14 @@
 t)) 
-%3C= 0) &&
+%3E 0 %7C%7C
 %0A   
@@ -3442,19 +3442,17 @@
         
-   
+!
 myContex
@@ -3463,19 +3463,20 @@
 Valid() 
-&& 
+%7C%7C !
 myContex
@@ -3516,34 +3516,153 @@
 ext)
- && getContainer() != null
+) return false;%0A%0A    final PsiDocCommentOwner container = getContainer();%0A    return container != null && !(container instanceof JspHolderMethod)
 ;%0A  

fix for jsps