/*
 * Copyright 2000-2013 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.
 */

/*
 * Created by IntelliJ IDEA.
 * User: mike
 * Date: Jun 7, 2002
 * Time: 8:30:35 PM
 * To change template for new class use
 * Code Style | Class Templates options (Tools | IDE Options).
 */
package com.intellij;

import com.intellij.idea.Bombed;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.TestRunnerUtil;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.*;
import java.util.List;

@SuppressWarnings({"HardCodedStringLiteral", "UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "TestOnlyProblems"})
public class TestCaseLoader {
  /** Holds name of JVM property that is assumed to define target test group name. */
  private static final String TARGET_TEST_GROUP = "idea.test.group";

  /** Holds name of JVM property that is assumed to define filtering rules for test classes. */
  private static final String TARGET_TEST_PATTERNS = "idea.test.patterns";

  public static final String PERFORMANCE_TESTS_ONLY_FLAG = "idea.performance.tests";
  public static final String SKIP_COMMUNITY_TESTS = "idea.skip.community.tests";

  private final List<Class> myClassList = new ArrayList<Class>();
  private Class myFirstTestClass;
  private Class myLastTestClass;
  private final TestClassesFilter myTestClassesFilter;
  private final boolean myIsPerformanceTestsRun;

  public TestCaseLoader(String classFilterName, boolean isPerformanceTestsRun) {
    myIsPerformanceTestsRun = isPerformanceTestsRun;

    String patterns = System.getProperty(TARGET_TEST_PATTERNS);
    if (patterns != null) {
      myTestClassesFilter = new PatternListTestClassFilter(StringUtil.split(patterns, ";"));
      System.out.println("Using patterns: [" + patterns +"]");
    }
    else {
      URL excludedStream = StringUtil.isEmpty(classFilterName) ? null : getClass().getClassLoader().getResource(classFilterName);
      if (excludedStream != null) {
        TestClassesFilter filter;
        try {
          String testGroupName = System.getProperty(TARGET_TEST_GROUP, "").trim();
          InputStreamReader reader = new InputStreamReader(excludedStream.openStream());
          try {
            filter = GroupBasedTestClassFilter.createOn(reader, testGroupName);
            System.out.println("Using test group: [" + testGroupName +"]");
          }
          finally {
            reader.close();
          }
        }
        catch (IOException e) {
          e.printStackTrace();
          filter = TestClassesFilter.ALL_CLASSES;
          System.out.println("Using all classes");
        }
        myTestClassesFilter = filter;
      }
      else {
        myTestClassesFilter = TestClassesFilter.ALL_CLASSES;
        System.out.println("Using all classes");
      }
    }
  }

  /*
   * Adds <code>testCaseClass</code> to the list of classes
   * if the class is a test case we wish to load. Calls
   * <code>shouldLoadTestCase ()</code> to determine that.
   */
  void addClassIfTestCase(Class testCaseClass) {
    if (shouldAddTestCase(testCaseClass, true) &&
        testCaseClass != myFirstTestClass && testCaseClass != myLastTestClass &&
        PlatformTestUtil.canRunTest(testCaseClass)) {
      myClassList.add(testCaseClass);
    }
  }

  void addFirstTest(Class aClass) {
    assert myFirstTestClass == null : "already added: "+aClass;
    assert shouldAddTestCase(aClass, false) : "not a test: "+aClass;
    myFirstTestClass = aClass;
  }

  void addLastTest(Class aClass) {
    assert myLastTestClass == null : "already added: "+aClass;
    assert shouldAddTestCase(aClass, false) : "not a test: "+aClass;
    myLastTestClass = aClass;
  }

  /**
   * Determine if we should load this test case.
   */
  private boolean shouldAddTestCase(final Class<?> testCaseClass, boolean testForExcluded) {
    if ((testCaseClass.getModifiers() & Modifier.ABSTRACT) != 0) return false;
    if (testForExcluded && shouldExcludeTestClass(testCaseClass)) return false;

    if (TestCase.class.isAssignableFrom(testCaseClass) || TestSuite.class.isAssignableFrom(testCaseClass)) {
      return true;
    }
    try {
      final Method suiteMethod = testCaseClass.getMethod("suite");
      if (Test.class.isAssignableFrom(suiteMethod.getReturnType()) && (suiteMethod.getModifiers() & Modifier.STATIC) != 0) {
        //System.out.println("testCaseClass = " + testCaseClass);
        return true;
      }
    }
    catch (NoSuchMethodException e) {
      // can't be
    }

    return TestRunnerUtil.isJUnit4TestClass(testCaseClass);
  }

  /*
   * Determine if we should exclude this test case.
   */
  private boolean shouldExcludeTestClass(Class testCaseClass) {
    String className = testCaseClass.getName();
    if (className.toLowerCase().contains("performance") && !myIsPerformanceTestsRun) return true;

    return !myTestClassesFilter.matches(className) || isBombed(testCaseClass);
  }

  public static boolean isBombed(final Method method) {
    final Bombed bombedAnnotation = method.getAnnotation(Bombed.class);
    if (bombedAnnotation == null) return false;
    if (PlatformTestUtil.isRotten(bombedAnnotation)) {
      String message = "Disarm the stale bomb for '" + method + "' in class '" + method.getDeclaringClass() + "'";
      System.err.println(message);
      //Assert.fail(message);
    }
    return !PlatformTestUtil.bombExplodes(bombedAnnotation);
  }

  public static boolean isBombed(final Class<?> testCaseClass) {
    final Bombed bombedAnnotation = testCaseClass.getAnnotation(Bombed.class);
    if (bombedAnnotation == null) return false;
    if (PlatformTestUtil.isRotten(bombedAnnotation)) {
      String message = "Disarm the stale bomb for '" + testCaseClass + "'";
      System.err.println(message);
     // Assert.fail(message);
    }
    return !PlatformTestUtil.bombExplodes(bombedAnnotation);
  }

  public void loadTestCases(final Collection<String> classNamesIterator) {
    for (String className : classNamesIterator) {
      try {
        Class candidateClass = Class.forName(className);
        addClassIfTestCase(candidateClass);
      }
      catch (ClassNotFoundException e) {
        System.err.println("Cannot load class " + className + ": " + e.getMessage());
        e.printStackTrace();
      }
      catch (ExceptionInInitializerError e) {
        System.err.println("Cannot initialize class " + className + ": " + e.getException().getMessage());
        e.printStackTrace();
        System.err.println("Root cause:");
        e.getException().printStackTrace();
      }
      catch (LinkageError e) {
        System.err.println("Cannot load class " + className + ": " + e.getMessage());
        e.printStackTrace();
      }
    }
  }

  private static final List<String> ourRankList = getTeamCityRankList();

  private static List<String> getTeamCityRankList() {
    final String filePath = System.getProperty("teamcity.tests.recentlyFailedTests.file", null);
    if (filePath == null) {
      return Collections.emptyList();
    }

    try {
      final List<String> result = new ArrayList<String>();
      final BufferedReader reader = new BufferedReader(new FileReader(filePath));
      try {
        do {
          final String className = reader.readLine();
          if (className == null) break;
          result.add(className);
        }
        while (true);
        return result;
      }
      finally {
        reader.close();
      }
    }
    catch (IOException e) {
      return Collections.emptyList();
    }
  }

  private int getRank(Class aClass) {
    final String name = aClass.getName();
    if (aClass == myFirstTestClass) return -1;
    if (aClass == myLastTestClass) return myClassList.size() + ourRankList.size();
    int i = ourRankList.indexOf(name);
    if (i != -1) {
      return i;
    }
    return ourRankList.size();
  }

  public List<Class> getClasses() {
    List<Class> result = new ArrayList<Class>(myClassList.size());
    if (myFirstTestClass != null) {
      result.add(myFirstTestClass);
    }
    result.addAll(myClassList);
    if (myLastTestClass != null) {
      result.add(myLastTestClass);
    }

    if (!ourRankList.isEmpty()) {
      Collections.sort(result, new Comparator<Class>() {
        @Override
        public int compare(final Class o1, final Class o2) {
          return getRank(o1) - getRank(o2);
        }
      });
    }

    return result;
  }

  public void clearClasses() {
    myClassList.clear();
  }
}
