/*
 * 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.theoryinpractice.testng.model;

import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.execution.configurations.ConfigurationUtil;
import com.intellij.ide.util.ClassFilter;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.theoryinpractice.testng.util.TestNGUtil;

/**
 * @author Hani Suleiman
 *         Date: Jul 21, 2005
 *         Time: 9:03:06 PM
 */
public class TestClassFilter implements ClassFilter.ClassFilterWithScope
{
    public static final String GUICE_INJECTION = "com.google.inject.Inject";

    private final GlobalSearchScope scope;
    private final Project project;
    private final boolean includeConfig;
    private final boolean checkClassCanBeInstantiated;


    public TestClassFilter(GlobalSearchScope scope, Project project, boolean includeConfig) {
      this(scope, project, includeConfig, false);
    }

    public TestClassFilter(GlobalSearchScope scope,
                           Project project,
                           boolean includeConfig,
                           boolean checkClassCanBeInstantiated) {
        this.scope = scope;
        this.project = project;
        this.includeConfig = includeConfig;
        this.checkClassCanBeInstantiated = checkClassCanBeInstantiated;
  }

    public TestClassFilter intersectionWith(GlobalSearchScope scope) {
        return new TestClassFilter(this.scope.intersectWith(scope), project, includeConfig, checkClassCanBeInstantiated);
    }

    public boolean isAccepted(PsiClass psiClass) {
        if(!ConfigurationUtil.PUBLIC_INSTANTIATABLE_CLASS.value(psiClass)) return false;
        //PsiManager manager = PsiManager.getInstance(project);
        //if(manager.getEffectiveLanguageLevel().compareTo(LanguageLevel.JDK_1_5) < 0) return true;
        boolean hasTest = TestNGUtil.hasTest(psiClass);
      if (hasTest) {
        if (checkClassCanBeInstantiated) {
          final PsiMethod[] constructors = psiClass.getConstructors();
          if (constructors.length > 0) {
            boolean canBeInstantiated = false;
            for (PsiMethod constructor : constructors) {
              if (constructor.getParameterList().getParametersCount() == 0) {
                canBeInstantiated = true;
                break;
              }
              if (AnnotationUtil.isAnnotated(constructor, GUICE_INJECTION, true)) {
                canBeInstantiated = true;
                break;
              }
            }
            if (!canBeInstantiated){
              return false;
            }
          }
        }
        return true;
      }

        return includeConfig && TestNGUtil.hasConfig(psiClass);
    }

    public Project getProject() {
        return project;
    }

    public GlobalSearchScope getScope() {
        return scope;
    }
}

@@ -1009,16 +1009,42 @@
 GUtil;%0A%0A
+import java.util.Arrays;%0A%0A
 /**%0A * @
@@ -1277,16 +1277,101 @@
 Inject%22;
+%0A    public static final String FACTORY_INJECTION = %22org.testng.annotations.Factory%22;
 %0A%0A    pr
@@ -3141,16 +3141,30 @@
 ructor, 
+Arrays.asList(
 GUICE_IN
@@ -3171,16 +3171,36 @@
 JECTION,
+ FACTORY_INJECTION),
  true)) 

allow to run tests when constructor parameters are injected by @Factory (IDEA-87716)