/*
 * Copyright 2000-2010 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.actions;

import com.intellij.analysis.AnalysisScope;
import com.intellij.analysis.AnalysisScopeBundle;
import com.intellij.analysis.AnalysisUIOptions;
import com.intellij.analysis.BaseAnalysisActionDialog;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
import com.intellij.codeInspection.ex.InspectionManagerEx;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.actions.GotoActionBase;
import com.intellij.ide.util.gotoByName.ChooseByNameFilter;
import com.intellij.ide.util.gotoByName.ChooseByNamePopup;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiSearchScopeUtil;
import com.intellij.psi.search.SearchScope;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.util.Arrays;

/**
 * @author Konstantin Bulenkov
 */
public class RunInspectionAction extends GotoActionBase {
  public RunInspectionAction() {
    getTemplatePresentation().setText(IdeBundle.message("goto.inspection.action.text"));
  }

  @Override
  protected void gotoActionPerformed(final AnActionEvent e) {
    final Project project = e.getData(PlatformDataKeys.PROJECT);
    if (project == null) return;

    PsiDocumentManager.getInstance(project).commitAllDocuments();

    final PsiElement psiElement = LangDataKeys.PSI_ELEMENT.getData(e.getDataContext());
    final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(e.getDataContext());
    final VirtualFile virtualFile = LangDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
    if (virtualFile == null) return;

    FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.inspection");

    final GotoInspectionModel model = new GotoInspectionModel(project);
    showNavigationPopup(e, model, new GotoActionCallback<Object>() {
      @Override
      protected ChooseByNameFilter<Object> createFilter(@NotNull ChooseByNamePopup popup) {
        popup.setSearchInAnyPlace(true);
        return super.createFilter(popup);
      }

      @Override
      public void elementChosen(ChooseByNamePopup popup, Object element) {
        runInspection(project, (InspectionProfileEntry)element, virtualFile, psiElement, psiFile);
      }
    });
  }

  private static void runInspection(@NotNull Project project,
                                    @NotNull InspectionProfileEntry profileEntry,
                                    @NotNull VirtualFile virtualFile,
                                    PsiElement psiElement, PsiFile psiFile) {
    final InspectionManagerEx managerEx = (InspectionManagerEx)InspectionManagerEx.getInstance(project);
    final Module module = ModuleUtil.findModuleForFile(virtualFile, project);

    AnalysisScope analysisScope = null;
    if (psiFile != null) {
      analysisScope = new AnalysisScope(psiFile);
    } else {
      if (virtualFile.isDirectory()) {
        final PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(virtualFile);
        if (psiDirectory != null) {
          analysisScope = new AnalysisScope(psiDirectory);
        }
      }
      if (analysisScope == null) {
        analysisScope = new AnalysisScope(project, Arrays.asList(virtualFile));
      }
    }

    final FileFilterPanel fileFilterPanel = new FileFilterPanel();
    fileFilterPanel.init();

    final BaseAnalysisActionDialog dlg = new BaseAnalysisActionDialog(
      AnalysisScopeBundle.message("specify.analysis.scope", InspectionsBundle.message("inspection.action.title")),
      AnalysisScopeBundle.message("analysis.scope.title", InspectionsBundle.message("inspection.action.noun")),
      project,
      analysisScope,
      module != null ? module.getName() : null,
      true,
      AnalysisUIOptions.getInstance(project),
      psiElement) {

      @Override
      protected JComponent getAdditionalActionSettings(Project project) {
        return fileFilterPanel.getPanel();
      }

      @Override
      public SearchScope getCustomScope() {
        return PsiSearchScopeUtil.union(fileFilterPanel.getSearchScope(), super.getCustomScope());
      }
    };

    AnalysisScope scope = analysisScope;
    dlg.show();
    if (!dlg.isOK()) return;
    final AnalysisUIOptions uiOptions = AnalysisUIOptions.getInstance(project);
    scope = dlg.getScope(uiOptions, scope, project, module);

    final InspectionProfileImpl profile = new InspectionProfileImpl(profileEntry.getDisplayName());
    final InspectionProfileImpl model = (InspectionProfileImpl)profile.getModifiableModel();
    model.disableAllTools();
    model.enableTool(profileEntry.getShortName());
    try {
      Element element = new Element("toCopy");
      profileEntry.writeSettings(element);
      model.getInspectionTool(profileEntry.getShortName()).readSettings(element);
    }
    catch (Exception e) {
      //skip
    }
    model.setEditable(profileEntry.getDisplayName());
    final GlobalInspectionContextImpl inspectionContext = managerEx.createNewGlobalContext(false);
    inspectionContext.setExternalProfile(model);
    inspectionContext.doInspections(scope, managerEx);
  }
}

@@ -837,16 +837,70 @@
 Dialog;%0A
+import com.intellij.codeInspection.InspectionManager;%0A
 import c
@@ -1990,16 +1990,59 @@
 NotNull;
+%0Aimport org.jetbrains.annotations.Nullable;
 %0A%0Aimport
@@ -2746,28 +2746,32 @@
 rtualFile = 
-Lang
+Platform
 DataKeys.VIR
@@ -2812,45 +2812,8 @@
 ());
-%0A    if (virtualFile == null) return;
 %0A%0A  
@@ -3633,22 +3633,23 @@
       @N
-otN
 ull
+able
  Virtual
@@ -3824,18 +3824,16 @@
 nManager
-Ex
 .getInst
@@ -3872,16 +3872,38 @@
 module =
+ virtualFile != null ?
  ModuleU
@@ -3945,16 +3945,23 @@
 project)
+ : null
 ;%0A%0A    A
@@ -4106,16 +4106,39 @@
 tualFile
+ != null && virtualFile
 .isDirec
@@ -4358,24 +4358,170 @@
   %7D%0A      %7D%0A
+      if (analysisScope == null && virtualFile != null) %7B%0A        analysisScope = new AnalysisScope(project, Arrays.asList(virtualFile));%0A      %7D%0A
       if (an
@@ -4596,36 +4596,8 @@
 ject
-, Arrays.asList(virtualFile)
 );%0A 

allow to run inspection by name when everything is closed