/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.google.appindexing.api;

import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import org.jetbrains.android.AndroidTestCase;
import org.jetbrains.annotations.NotNull;

public class ApiCreatorTest extends AndroidTestCase {
  private static final String BASE_PATH = PathManager.getHomePath() + "/../studio/google/appindexing/testData/ApiCreator";

  private static final String ANDROID_MANIFEST = "AndroidManifest.xml";
  private static final String CARET_NOT_IN_JAVA_FILE = "caret_not_in_java_file.xml";
  private static final String JAVA_FILE_CARET_OUTSIDE_ACTIVITY = "src/CaretOutsideActivity.java";
  private static final String JAVA_FILE_NOT_ACTIVITY = "src/NotActivity.java";
  private static final String JAVA_FILE_HAS_APP_INDEXING_START_AND_END = "src/HasAppIndexingStartAndEnd.java";
  private static final String JAVA_FILE_SPECIAL_STATEMENT = "src/SpecialStatement.java";
  private static final String JAVA_FILE_EMPTY_ACTIVITY = "src/EmptyActivity.java";
  private static final String JAVA_FILE_EMPTY_ACTIVITY_AFTER = "src/EmptyActivity_after.java";
  private static final String JAVA_FILE_CONFLICT_IMPORTS = "src/ConflictImports.java";
  private static final String JAVA_FILE_CONFLICT_IMPORTS_AFTER = "src/ConflictImports_after.java";
  private static final String JAVA_FILE_WILD_CARD_IMPORTS = "src/WildCardImports.java";
  private static final String JAVA_FILE_WILD_CARD_IMPORTS_AFTER = "src/WildCardImports_after.java";
  private static final String JAVA_FILE_ONLY_START_CALL = "src/OnlyStartCall.java";
  private static final String JAVA_FILE_ONLY_START_CALL_AFTER = "src/OnlyStartCall_after.java";
  private static final String JAVA_FILE_ONLY_END_CALL = "src/OnlyEndCall.java";
  private static final String JAVA_FILE_ONLY_END_CALL_AFTER = "src/OnlyEndCall_after.java";
  private static final String JAVA_FILE_OVERRIDE_METHOD = "src/OverrideMethod.java";
  private static final String JAVA_FILE_OVERRIDE_METHOD_AFTER = "src/OverrideMethod_after.java";
  private static final String JAVA_FILE_NO_KEYWORD_SUPER = "src/NoKeywordSuper.java";
  private static final String JAVA_FILE_NO_KEYWORD_SUPER_AFTER = "src/NoKeywordSuper_after.java";
  private static final String JAVA_FILE_CONFLICT_METHOD_NAME = "src/ConflictGetActionMethodName.java";
  private static final String JAVA_FILE_CONFLICT_METHOD_NAME_AFTER = "src/ConflictGetActionMethodName_after.java";

  @Override
  protected boolean providesCustomManifest() {
    return true;
  }

  @Override
  public void setUp() throws Exception {
    super.setUp();
    myFixture.setTestDataPath(BASE_PATH);
    TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
    // Set an empty temporary code style. Otherwise, the variable name will follow users' custom setting.
    CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(myFixture.getProject());
    codeStyleSettings.clearCodeStyleSettings();
    CodeStyleSettingsManager.getInstance().setTemporarySettings(codeStyleSettings);
  }

  @Override
  public void tearDown() throws Exception {
    super.tearDown();
    CodeStyleSettingsManager.getInstance().dropTemporarySettings();
  }

  public void testCaretInAndroidManifest() throws Exception {
    doEnableTest(CARET_NOT_IN_JAVA_FILE, false);
  }

  public void testCaretOutsideActivity() throws Exception {
    doEnableTest(JAVA_FILE_CARET_OUTSIDE_ACTIVITY, false);
  }

  public void testClassNotInheritActivity() throws Exception {
    doEnableTest(JAVA_FILE_NOT_ACTIVITY, false);
  }

  public void testHasAppIndexingApiStartAndEnd() throws Exception {
    doEnableTest(JAVA_FILE_HAS_APP_INDEXING_START_AND_END, false);
  }

  /**
   * The app indexing APIs are used in special statements,
   * such as block statements, declaration statements and loop statement.
   */
  public void testSpecialStatement() throws Exception {
    doEnableTest(JAVA_FILE_SPECIAL_STATEMENT, false);
  }

  public void testEmptyActivity() throws Exception {
    doJavaFileTest(JAVA_FILE_EMPTY_ACTIVITY, JAVA_FILE_EMPTY_ACTIVITY_AFTER);
  }

  public void testConflictImports() throws Exception {
    doJavaFileTest(JAVA_FILE_CONFLICT_IMPORTS, JAVA_FILE_CONFLICT_IMPORTS_AFTER);
  }

  public void testWildCardImports() throws Exception {
    doJavaFileTest(JAVA_FILE_WILD_CARD_IMPORTS, JAVA_FILE_WILD_CARD_IMPORTS_AFTER);
  }

  public void testOnlyAppIndexingStart() throws Exception {
    doJavaFileTest(JAVA_FILE_ONLY_START_CALL, JAVA_FILE_ONLY_START_CALL_AFTER);
  }

  public void testOnlyAppIndexingEnd() throws Exception {
    doJavaFileTest(JAVA_FILE_ONLY_END_CALL, JAVA_FILE_ONLY_END_CALL_AFTER);
  }

  public void testWithOverridingMethod() throws Exception {
    doJavaFileTest(JAVA_FILE_OVERRIDE_METHOD, JAVA_FILE_OVERRIDE_METHOD_AFTER);
  }

  /**
   * Tests class with overriding method but not invoking overridden method through keyword super
   */
  public void testNoKeywordSuper() throws Exception {
    doJavaFileTest(JAVA_FILE_NO_KEYWORD_SUPER, JAVA_FILE_NO_KEYWORD_SUPER_AFTER);
  }

  /**
   * Tests class with conflicted method name.
   */
  public void testConflictMethodName() throws Exception {
    doJavaFileTest(JAVA_FILE_CONFLICT_METHOD_NAME, JAVA_FILE_CONFLICT_METHOD_NAME_AFTER);
  }

  /**
   * Tests whether the project is eligible for App Indexing API code inserting.
   *
   * @param filePath The path of the Java source file.
   * @param enable   If the creator (generator / intention) should be enabled.
   */
  private void doEnableTest(@NotNull String filePath, boolean enable) {
    myFixture.configureByFiles(filePath);
    assertEquals(ApiCreator.eligibleForInsertingAppIndexingApiCode(myFixture.getEditor(), myFixture.getFile()), enable);
  }

  /**
   * Test for creation in Java source file.
   */
  private void doJavaFileTest(@NotNull String testFilePath, @NotNull String expectedFilePath) {
    myFixture.configureByFiles(testFilePath);
    myFixture.copyFileToProject(ANDROID_MANIFEST);
    final ApiCreator creator = new ApiCreator(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile());
    CommandProcessor.getInstance().executeCommand(null, new Runnable() {
      @Override
      public void run() {
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
          @Override
          public void run() {
            creator.insertAppIndexingApiCodeInJavaFile(creator.getDeepLinkOfActivity());
          }
        });
      }
    }, null, null);

    VirtualFile expectedFile = myFixture.copyFileToProject(expectedFilePath);
    PsiFile expectedPsiFile = PsiManager.getInstance(myFixture.getProject()).findFile(expectedFile);
    assertNotNull(expectedPsiFile);
    String normalizedTestFile = getNormalizedContent(myFixture.getFile()).replace("<caret>", "");
    assertEquals(normalizedTestFile, getNormalizedContent(expectedPsiFile));
  }


  /**
   * Normalizes file content: remove java.lang imports, comments, white space and line terminators.
   *
   * @param file The file to normalize.
   * @return The normalized content.
   */
  protected static String getNormalizedContent(@NotNull final PsiFile file) {
    StringBuilder stringBuilder = new StringBuilder();
    // Removes line terminators.
    Iterable<String> lines = Splitter.onPattern("\r?\n").omitEmptyStrings().split(file.getText());
    for (String line : lines) {
      line = CharMatcher.WHITESPACE.removeFrom(line);
      // Removes import statements of classes from java.lang package if it is a Java file.
      // Because Android Studio will automatically import them.
      if (line.startsWith("importjava.lang.")) {
        continue;
      }
      stringBuilder.append(line);
    }
    return stringBuilder.toString();
  }

  @NotNull
  protected String getGradleRelativePath() {
    StringBuilder builder = new StringBuilder();
    String projectPath = myFixture.getProject().getBasePath();
    while (projectPath != null && projectPath.contains("/")) {
      projectPath = projectPath.substring(0, projectPath.lastIndexOf("/"));
      builder.append("../");
    }
    builder.deleteCharAt(builder.length() - 1);
    String moduleFilePath = myModule.getModuleFilePath();
    builder.append(moduleFilePath.substring(0, moduleFilePath.lastIndexOf("/")));
    builder.append("/build.gradle");
    return builder.toString();
  }
}
