/*
 * 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.android.SdkConstants;
import com.android.annotations.VisibleForTesting;
import com.android.builder.model.AndroidArtifact;
import com.android.builder.model.AndroidLibrary;
import com.android.builder.model.Dependencies;
import com.android.builder.model.MavenCoordinates;
import com.android.ide.common.repository.GradleCoordinate;
import com.android.tools.idea.gradle.project.model.AndroidModuleModel;
import com.android.tools.idea.gradle.dsl.model.GradleBuildModel;
import com.android.tools.idea.gradle.dsl.model.dependencies.ArtifactDependencyModel;
import com.android.tools.idea.gradle.dsl.model.dependencies.ArtifactDependencySpec;
import com.android.tools.idea.gradle.dsl.model.dependencies.DependenciesModel;
import com.android.tools.idea.gradle.project.sync.GradleSyncInvoker;
import com.google.appindexing.util.DeepLinkUtils;
import com.google.appindexing.util.ManifestUtils;
import com.google.common.base.CharMatcher;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlComment;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.siyeh.ig.psiutils.ImportUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.android.tools.idea.gradle.dsl.model.dependencies.CommonConfigurationNames.COMPILE;
import static com.android.tools.idea.gradle.util.GradleUtil.getDependencies;

/**
 * A class for detecting the situation where developers need App Indexing API code and inserting
 * the API code in their projects.
 */
public final class ApiCreator {
  static private final String COMPILE_GMS_GROUP = "com.google.android.gms";
  static private final String COMPILE_APPINDEXING = "play-services-appindexing";
  static private final String MINIMUM_VERSION = "8.4.0";

  static private final String TAG_METADATA = "meta-data";
  static private final String ATTR_NAME_METADATA_GMS = "com.google.android.gms.version";
  static private final String ATTR_VALUE_METADATA_GMS = "@integer/google_play_services_version";

  static private final String METHOD_GET_ACTION = "getIndexApiAction";

  static private final String CLASS_ACTION = "Action";
  static private final String CLASS_APP_INDEX = "AppIndex";
  static private final String CLASS_GOOGLE_API_CLIENT = "GoogleApiClient";
  static private final String CLASS_THING = "Thing";
  static private final String CLASS_ACTION_FULL = "com.google.android.gms.appindexing.Action";
  static private final String CLASS_APP_INDEX_FULL = "com.google.android.gms.appindexing.AppIndex";
  static private final String CLASS_THING_FULL = "com.google.android.gms.appindexing.Thing";
  static private final String CLASS_GOOGLE_API_CLIENT_FULL = "com.google.android.gms.common.api.GoogleApiClient";

  static private final List<String> SIGNATURE_ON_CREATE = Lists.newArrayList("android.os.Bundle");
  static private final List<String> SIGNATURE_ON_START = Lists.newArrayList();
  static private final List<String> SIGNATURE_ON_STOP = Lists.newArrayList();
  static private final String ON_CREATE_FORMAT = "@Override\n" +
                                                 "protected void onCreate(android.os.Bundle savedInstanceState) {\n" +
                                                 "  super.onCreate(savedInstanceState);\n" +
                                                 "  \n" +
                                                 "  // ATTENTION: This was auto-generated to implement the App Indexing API.\n" +
                                                 "  // See https://g.co/AppIndexing/AndroidStudio for more information.\n" +
                                                 "  %1$s = new %2$s.Builder(this).addApi(%3$s.API).build();\n" +
                                                 "}";
  static private final String ON_START_FORMAT = "@Override\n" +
                                                "public void onStart(){\n" +
                                                "  super.onStart();\n" +
                                                "  \n" +
                                                "  // ATTENTION: This was auto-generated to implement the App Indexing API.\n" +
                                                "  // See https://g.co/AppIndexing/AndroidStudio for more information.\n" +
                                                "  %1$s.connect();\n" +
                                                "  %3$s.AppIndexApi.start(%1$s, %2$s);\n" +
                                                "}";
  static private final String ON_STOP_FORMAT = "@Override\n" +
                                               "public void onStop() {\n" +
                                               "  super.onStop();\n" +
                                               "  \n" +
                                               "  // ATTENTION: This was auto-generated to implement the App Indexing API.\n" +
                                               "  // See https://g.co/AppIndexing/AndroidStudio for more information.\n" +
                                               "  %3$s.AppIndexApi.end(%1$s, %2$s);\n" +
                                               "  %1$s.disconnect();\n" +
                                               "}";

  static private final String GET_ACTION_FORMAT = "/**\n" +
                                                  " * ATTENTION: This was auto-generated to implement the App Indexing API.\n" +
                                                  " * See https://g.co/AppIndexing/AndroidStudio for more information.\n" +
                                                  " */\n" +
                                                  "public %4$s %1$s() {\n" +
                                                  "  %5$s object = new %5$s.Builder()\n" +
                                                  "      .setName(\"%2$s Page\") // TODO: Define a title for the content shown.\n" +
                                                  "      // TODO: Make sure this auto-generated URL is correct.\n" +
                                                  "      .setUrl(android.net.Uri.parse(\"%3$s\"))\n" +
                                                  "      .build();\n" +
                                                  "  return new %4$s.Builder(%4$s.TYPE_VIEW)\n" +
                                                  "      .setObject(object)\n" +
                                                  "      .setActionStatus(%4$s.STATUS_TYPE_COMPLETED)\n" +
                                                  "      .build();\n" +
                                                  "}";

  static private final String CLIENT_FORMAT = "%1$s = new %2$s.Builder(this).addApi(%3$s.API).build();";
  static private final String BUILDER_APPINDEXAPI = ".addApi(%s.API)";
  static private final String APP_INDEXING_START = "%3$s.AppIndexApi.start(%1$s,%2$s);";
  static private final String APP_INDEXING_END = "%3$s.AppIndexApi.end(%1$s,%2$s);";
  static private final String APP_INDEXING_START_HALF = "AppIndexApi.start(%1$s,";
  static private final String APP_INDEXING_END_HALF = "AppIndexApi.end(%1$s,";
  static private final String APP_INDEXING_VIEW = "AppIndexApi.view(%1$s,";
  static private final String APP_INDEXING_VIEWEND = "AppIndexApi.viewEnd(%1$s,";

  static private final List<String> COMMENT_BUILDER_APPINDEXAPI = Lists
    .newArrayList("// ATTENTION: This \"addApi(AppIndex.API)\"was auto-generated to implement the App Indexing API.",
                  "// See https://g.co/AppIndexing/AndroidStudio for more information.");
  static private final List<String> COMMENT_IN_JAVA = Lists
    .newArrayList("// ATTENTION: This was auto-generated to implement the App Indexing API.",
                  "// See https://g.co/AppIndexing/AndroidStudio for more information.");
  static private final String COMMENT_FOR_FIELD = "/**\n" +
                                                  " * ATTENTION: This %1$swas auto-generated to implement the App Indexing API.\n" +
                                                  " * See https://g.co/AppIndexing/AndroidStudio for more information.\n" +
                                                  " */";
  static private final String COMMENT_IN_MANIFEST =
    "<!-- ATTENTION: This was auto-generated to add Google Play services to your project for\n" +
    "     App Indexing.  See https://g.co/AppIndexing/AndroidStudio for more information. -->";

  /* To prompt developers to update deep link url, sets default url to a noticeable wrong url */
  static private final String DEFAULT_DEEP_LINK_URL = "http://[ENTER-YOUR-URL-HERE]";


  private Project myProject = null;
  private Module myModule = null;
  private PsiFile myFile = null;

  private PsiClass myActivity = null;

  private PsiElementFactory myFactory = null;
  private CodeStyleManager myCodeStyleManager = null;

  private PsiCodeBlock myOnCreate = null;
  private PsiCodeBlock myOnStart = null;
  private PsiCodeBlock myOnStop = null;

  /* The App Indexing API statements in onStart / onStop method */
  private List<PsiStatement> myStartStatements = Lists.newArrayList();
  private List<PsiStatement> myEndStatements = Lists.newArrayList();
  private List<PsiStatement> myViewStatements = Lists.newArrayList();
  private List<PsiStatement> myViewEndStatements = Lists.newArrayList();

  private String myHighestGmsLibVersion = null;
  private String myAppIndexingLibVersion = null;

  private Map<String, String> myImportClasses = Maps.newHashMap();

  public ApiCreator(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
    myProject = project;
    myFile = file;
    myModule = ModuleUtilCore.findModuleForFile(myFile.getVirtualFile(), myProject);

    if (myFile instanceof PsiJavaFile) {
      PsiElement element = myFile.findElementAt(editor.getCaretModel().getOffset());
      if (element != null) {
        myActivity = getSurroundingInheritingClass(element, SdkConstants.CLASS_ACTIVITY);
        if (myActivity != null) {
          myOnCreate = getMethodBodyByName("onCreate", SIGNATURE_ON_CREATE, myActivity);
          myOnStart = getMethodBodyByName("onStart", SIGNATURE_ON_START, myActivity);
          myOnStop = getMethodBodyByName("onStop", SIGNATURE_ON_STOP, myActivity);
          if (myOnStart != null) {
            myStartStatements = StatementFilter.filterCodeBlock("AppIndex.AppIndexApi.start", myOnStart);
            myViewStatements = StatementFilter.filterCodeBlock("AppIndex.AppIndexApi.view", myOnStart);
          }
          if (myOnStop != null) {
            myEndStatements = StatementFilter.filterCodeBlock("AppIndex.AppIndexApi.end", myOnStop);
            myViewEndStatements = StatementFilter.filterCodeBlock("AppIndex.AppIndexApi.viewEnd", myOnStop);
          }
        }
      }
    }
    myFactory = (PsiElementFactory)JVMElementFactories.getFactory(JavaLanguage.INSTANCE, myProject);
    myCodeStyleManager = CodeStyleManager.getInstance(myProject);
    myImportClasses.put(CLASS_ACTION, CLASS_ACTION_FULL);
    myImportClasses.put(CLASS_APP_INDEX, CLASS_APP_INDEX_FULL);
    myImportClasses.put(CLASS_GOOGLE_API_CLIENT, CLASS_GOOGLE_API_CLIENT_FULL);
    myImportClasses.put(CLASS_THING, CLASS_THING_FULL);
  }

  @VisibleForTesting
  void setGmsLibVersion(@Nullable String version) {
    myHighestGmsLibVersion = version;
    myAppIndexingLibVersion = version;
  }

  /**
   * If the current caret's position is eligible for creating App Indexing API code,
   * i.e. the caret is inside an 'Activity' class
   * and the class does not call app indexing api.
   *
   * @return true if the current caret's position needs app indexing generating intention.
   */
  public static boolean eligibleForInsertingAppIndexingApiCode(@NotNull Editor editor, @NotNull PsiFile file) {
    if (!(file instanceof PsiJavaFile)) return false;
    PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
    if (element == null) return false;
    PsiClass activity = getSurroundingInheritingClass(element, SdkConstants.CLASS_ACTIVITY);
    if (activity == null) return false;
    PsiCodeBlock onStart = getMethodBodyByName("onStart", SIGNATURE_ON_START, activity);
    if (onStart == null) return true;
    PsiCodeBlock onStop = getMethodBodyByName("onStop", SIGNATURE_ON_STOP, activity);
    if (onStop == null) return true;
    List<PsiStatement> startStatements = StatementFilter.filterCodeBlock("AppIndexApi.start", onStart);
    List<PsiStatement> viewStatements = StatementFilter.filterCodeBlock("AppIndexApi.view", onStart);
    if (startStatements.isEmpty() && viewStatements.isEmpty()) return true;
    List<PsiStatement> endStatements = StatementFilter.filterCodeBlock("AppIndexApi.end", onStop);
    List<PsiStatement> viewEndStatements = StatementFilter.filterCodeBlock("AppIndexApi.viewEnd", onStop);
    if (endStatements.isEmpty() && viewEndStatements.isEmpty()) return true;
    return false;
  }

  /**
   * Inserts the AppIndexing API code for the activity where the caret is in.
   * Steps:
   * 1. Generates Google Play Service Support in build.gradle and AndroidManifest.xml of current
   * module.
   * 2. Generates App Indexing API code in Java source file.
   * 3. Sync the project if build.gradle of module is changed.
   */
  public void insertAppIndexingApiCodeForActivity() {
    boolean needGradleSync = false;
    try {
      if (myModule == null || myActivity == null || myFactory == null || myCodeStyleManager == null) {
        Logger.getInstance(ApiCreator.class).info("Unable to generate App Indexing API code.");
        return;
      }

      getGmsDependencyVersion();
      needGradleSync = insertGmsCompileDependencyInGradleIfNeeded();

      XmlFile manifestPsiFile = ManifestUtils.getAndroidManifestPsi(myModule);
      if (manifestPsiFile == null) {
        Logger.getInstance(ApiCreator.class).info("AndroidManifest.xml not found.");
        return;
      }
      insertGmsVersionTagInManifestIfNeeded(manifestPsiFile);

      insertAppIndexingApiCodeInJavaFile(getDeepLinkOfActivity(), !needGradleSync);
    }
    catch (ApiCreatorException e) {
      e.printStackTrace();
    }
    finally {
      if (needGradleSync) {
        GradleSyncInvoker.getInstance().requestProjectSyncAndSourceGeneration(myProject, null);
      }
    }
  }

  private void getGmsDependencyVersion() throws ApiCreatorException {
    AndroidModuleModel model = AndroidModuleModel.get(myModule);
    if (model == null) {
      throw new ApiCreatorException("AndroidGradleModel not found.");
    }
    AndroidArtifact artifact = model.getMainArtifact();
    Dependencies dependencies = getDependencies(artifact, model.getModelVersion());
    Collection<AndroidLibrary> libraries = dependencies.getLibraries();
    for (AndroidLibrary library : libraries) {
      getDependencyVersionFromAndroidLibrary(library);
    }
  }

  private void getDependencyVersionFromAndroidLibrary(AndroidLibrary library) {
    MavenCoordinates coordinates = library.getResolvedCoordinates();
    if (coordinates != null && coordinates.getGroupId().equals(COMPILE_GMS_GROUP)) {
      String version = coordinates.getVersion();
      if (coordinates.getArtifactId().equals(COMPILE_APPINDEXING)) {
        myAppIndexingLibVersion = version;
      }
      if (myHighestGmsLibVersion == null || compareVersion(version, myHighestGmsLibVersion) > 0) {
        myHighestGmsLibVersion = version;
      }
    }

    for (AndroidLibrary dependency : library.getLibraryDependencies()) {
      getDependencyVersionFromAndroidLibrary(dependency);
    }
  }

  /**
   * Generates App Indexing Support in build.gradle of app module, if no such support exists.
   *
   * @return true if gradle myFile is changed and needs sync.
   */
  @VisibleForTesting
  boolean insertGmsCompileDependencyInGradleIfNeeded() throws ApiCreatorException {
    GradleBuildModel buildModel = GradleBuildModel.get(myModule);
    if (buildModel == null) {
      throw new ApiCreatorException("Build model not found.");
    }
    DependenciesModel dependencies = buildModel.dependencies();
    String versionToUse = MINIMUM_VERSION;
    if (myHighestGmsLibVersion != null && compareVersion(myHighestGmsLibVersion, MINIMUM_VERSION) > 0) {
      versionToUse = myHighestGmsLibVersion;
    }

    boolean gradleChange = false;
    if (myAppIndexingLibVersion == null) {
      ArtifactDependencySpec newDependency = new ArtifactDependencySpec(COMPILE_APPINDEXING, COMPILE_GMS_GROUP, versionToUse);
      dependencies = buildModel.dependencies();
      dependencies.addArtifact(COMPILE, newDependency);
      buildModel.applyChanges();
      gradleChange = true;
    }

    if (myHighestGmsLibVersion != null && compareVersion(myHighestGmsLibVersion, versionToUse) < 0) {
      List<ArtifactDependencyModel> dependencyList = dependencies.artifacts();
      for (ArtifactDependencyModel dependency : dependencyList) {
        String group = dependency.group().value();
        if (group != null && group.equals(COMPILE_GMS_GROUP)) {
          dependency.setVersion(versionToUse);
          buildModel.applyChanges();
          gradleChange = true;
        }
      }
    }
    return gradleChange;
  }

  /**
   * Generates App Indexing Support in AndroidManifest.xml.
   *
   * @param manifestPsiFile The psi file of AndroidManifest.xml.
   */
  @VisibleForTesting
  void insertGmsVersionTagInManifestIfNeeded(@NotNull XmlFile manifestPsiFile) {
    XmlTag root = manifestPsiFile.getRootTag();
    if (root != null) {
      List<XmlTag> applications = ManifestUtils.searchXmlTagsByName(root, SdkConstants.TAG_APPLICATION);
      for (XmlTag application : applications) {
        if (getGmsTag(application) == null) {
          XmlTag gms = application.createChildTag(TAG_METADATA, null, null, false);
          gms = application.addSubTag(gms, false);
          gms.setAttribute(SdkConstants.ATTR_NAME, SdkConstants.ANDROID_URI, ATTR_NAME_METADATA_GMS);
          gms.setAttribute(SdkConstants.ATTR_VALUE, SdkConstants.ANDROID_URI, ATTR_VALUE_METADATA_GMS);

          XmlTag GmsTag = getGmsTag(application);
          XmlComment comment = createXmlComment(COMMENT_IN_MANIFEST);
          if (comment != null && GmsTag != null) {
            application.addBefore(comment, GmsTag);
          }
        }
      }
      unlockFromPsiOperation(manifestPsiFile);
    }
  }

  /**
   * Generates App Indexing API code in Java source file.
   * Steps:
   * 1. Generates import statements in activity class.
   * 2. Generates GoogleApiClient variable.
   * The method will firstly scan the code to find existing App Indexing API call to get
   * GoogleApiClient candidate. Then verify if the candidate could be reused in the generated
   * code - it's a class member and the initialization can be adjusted to add App Indexing API.
   * If not, a new GoogleApiClient class member will be created.
   * 3. Generates App Indexing API call in activity.
   *
   * @param deepLink                  The deep link for the activity. It may be nullable, because
   *                                  we should deal with situation where no deep link is specified
   *                                  in AndroidManifest.xml.
   * @param withAppIndexingDependency If gradle will be sync later.
   */
  @VisibleForTesting
  void insertAppIndexingApiCodeInJavaFile(@Nullable String deepLink, boolean withAppIndexingDependency) {
    insertImportStatements(withAppIndexingDependency);

    String clientName = null, clientNameCandidate = null;
    List<PsiStatement> statementsAppIndexApi = getAppIndexApiStatement();
    for (PsiStatement statementAppIndexApi : statementsAppIndexApi) {
      clientNameCandidate = getClientInAppIndexingApi(statementAppIndexApi);
      if (clientNameCandidate != null) {
        break;
      }
    }
    if (clientNameCandidate == null) {
      List<String> clientNames = getFieldNameByType(CLASS_GOOGLE_API_CLIENT);
      if (!clientNames.isEmpty()) {
        clientNameCandidate = clientNames.get(0);
      }
    }
    if (clientNameCandidate != null) {
      PsiField clientField = getFieldByName(clientNameCandidate);
      PsiStatement clientInitStatement = null;
      if (clientField != null && !clientField.hasInitializer()) {
        clientInitStatement = getClientInitStatements(clientNameCandidate);
      }
      // Adjusts client's initialization to add AppIndexing API.
      if (clientField != null) {
        boolean adjustmentSucceed = false;
        if (clientField.hasInitializer()) {
          adjustmentSucceed = adjustClientFieldInitializerIfNeeded(clientField);
        }
        else if (clientInitStatement != null) {
          adjustmentSucceed = adjustClientInitStatementIfNeeded(clientInitStatement);
        }
        if (adjustmentSucceed) {
          clientName = clientNameCandidate;
        }
      }
    }
    if (clientName == null) {
      // Creates a class member with GoogleApiClient type, and initializes it at onCreate method.
      clientName = createGoogleApiClientField();
    }

    String getActionMethodCallText = insertGetActionMethod(deepLink) + "()";
    addOrMergeOnStart(clientName, getActionMethodCallText);
    addOrMergeOnStop(clientName, getActionMethodCallText);

    JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(myActivity);

    unlockFromPsiOperation(myFile);
  }

  /**
   * Insert a method which construct Action instance and return it. Return the name of the method inserted.
   * @param deepLink The deeplink used to construct the Action instance.
   * @return The name of the method inserted.
   */
  @NotNull
  private String insertGetActionMethod(@Nullable String deepLink) {
    String methodName = getUnusedMethodName(METHOD_GET_ACTION);
    String pageName = myActivity.getName();
    if (pageName.endsWith("Activity")) {
      pageName = pageName.substring(0, pageName.length() - 8);
    }
    String url = deepLink == null ? DEFAULT_DEEP_LINK_URL : deepLink;
    String getActionMethod = String.format(
        GET_ACTION_FORMAT, methodName, pageName, url, myImportClasses.get(CLASS_ACTION), myImportClasses.get(CLASS_THING));
    PsiMethod newGetAction = myFactory.createMethodFromText(getActionMethod, null);
    myActivity.add(newGetAction);
    return methodName;
  }

  @NotNull
  private String getUnusedMethodName(@NotNull String methodName) {
    PsiMethod[] psiMethods = myActivity.getMethods();
    Set<String> usedMethodNames = Sets.newHashSet();
    for (PsiMethod p : psiMethods) {
      usedMethodNames.add(p.getName());
    }
    String unusedMethodName = methodName;
    for (int suffix = 0; usedMethodNames.contains(unusedMethodName); suffix++) {
      unusedMethodName = methodName + suffix;
    }
    return unusedMethodName;
  };

  /**
   * Generates import statements of app indexing Java Code.
   *
   * @param withAppIndexingDependency If gradle will be sync later.
   */
  private void insertImportStatements(boolean withAppIndexingDependency) {
    if (!withAppIndexingDependency) {
      // Without App Indexing dependency, App-Indexing-related classes cannot be found,
      // so "shortenClassReferences" cannot be used.
      for (Map.Entry<String, String> className : myImportClasses.entrySet()) {
        if (!ImportUtils.hasOnDemandImportConflict(className.getValue(), myActivity) &&
            !hasExactImportConflict(className.getValue(), (PsiJavaFile)myFile)) {
          insertSingleImportIfNeeded(className.getValue());
          className.setValue(className.getKey());
        }
      }
    }
  }

  // Copied from ImportUtils - where it was made private in 1.5 so we can't call it directly.
  private static boolean hasExactImportConflict(String fqName, PsiJavaFile file) {
    final PsiImportList imports = file.getImportList();
    if (imports == null) {
      return false;
    }
    final PsiImportStatement[] importStatements = imports.getImportStatements();
    final int lastDotIndex = fqName.lastIndexOf((int)'.');
    final String shortName = fqName.substring(lastDotIndex + 1);
    final String dottedShortName = '.' + shortName;
    for (final PsiImportStatement importStatement : importStatements) {
      if (importStatement.isOnDemand()) {
        continue;
      }
      final String importName = importStatement.getQualifiedName();
      if (importName == null) {
        return false;
      }
      if (!importName.equals(fqName) && importName.endsWith(dottedShortName)) {
        return true;
      }
    }
    return false;
  }


  /**
   * Searches App Indexing API call in onStart & onStop.
   *
   * @return All the App Indexing API call found.
   */
  @NotNull
  private List<PsiStatement> getAppIndexApiStatement() {
    List<PsiStatement> result = Lists.newArrayList(myStartStatements);
    result.addAll(myViewStatements);
    if (!result.isEmpty()) {
      return result;
    }
    result.addAll(myEndStatements);
    result.addAll(myViewEndStatements);
    return result;
  }

  /**
   * Gets all assignment statements of the client in onCreate.
   *
   * @param clientName The GoogleApiClient name.
   * @return All the init statements.
   */
  @Nullable
  private PsiStatement getClientInitStatements(@NotNull String clientName) {
    if (myOnCreate != null) {
      List<PsiStatement> statements = StatementFilter.filterCodeBlock(".build()", myOnCreate);
      for (PsiStatement statement : statements) {
        if (statement instanceof PsiExpressionStatement) {
          PsiType statementType = ((PsiExpressionStatement)statement).getExpression().getType();
          if (statementType != null &&
              statementType.getPresentableText().equals(CLASS_GOOGLE_API_CLIENT) &&
              CharMatcher.WHITESPACE.removeFrom(statement.getText()).startsWith(clientName + "=")) {
            return statement;
          }
        }
      }
    }
    return null;
  }

  /**
   * Adjusts the initializer of the client field to add App Indexing API,
   * if there is the initializer ends with ".build()" and have not added App Indexing API.
   *
   * @param clientField The client field.
   * @return true if the adjustment succeeds, i.e. the initializer has added App Indexing API.
   */
  private boolean adjustClientFieldInitializerIfNeeded(@NotNull PsiField clientField) {
    PsiExpression clientInitializer = clientField.getInitializer();
    if (clientInitializer != null) {
      String oldInitializerText = clientInitializer.getText();
      String newInitializerText = generateApiClientInitializeString(oldInitializerText);
      if (newInitializerText != null) {
        if (!newInitializerText.equals(oldInitializerText)) {
          clientField.setInitializer(myFactory.createExpressionFromText(newInitializerText, null));
          String commentText = String.format(COMMENT_FOR_FIELD, "\"addApi(AppIndex.API)\" ");
          myActivity.addBefore(myFactory.createCommentFromText(commentText, null), clientField);
        }
        return true;
      }
    }
    return false;
  }

  /**
   * Adjusts the the client initializing statement to add AppIndexing API,
   * if there is the initializer ends with ".build()" and have not added App Indexing API.
   *
   * @param statement The init statement of client.
   * @return true if the adjustment succeeds, i.e. the statement has added App Indexing API.
   */
  private boolean adjustClientInitStatementIfNeeded(@NotNull PsiStatement statement) {
    String oldText = statement.getText();
    String newText = generateApiClientInitializeString(oldText);
    if (newText != null) {
      PsiElement newStatement = statement.replace(myFactory.createStatementFromText(newText, null));
      if (!newText.equals(oldText)) {
        addCommentsBefore(COMMENT_BUILDER_APPINDEXAPI, myOnCreate, newStatement);
      }
      return true;
    }
    return false;
  }

  /**
   * Creates a class member with GoogleApiClient type, and initializes it at onCreate method.
   *
   * @return The GoogleApiClient name.
   */
  @NotNull
  private String createGoogleApiClientField() {
    String clientName = getUnusedName("client", VariableKind.FIELD);
    PsiClassType type = myFactory.createTypeByFQClassName(myImportClasses.get(CLASS_GOOGLE_API_CLIENT));
    PsiField clientField = (PsiField)myActivity.add(myFactory.createField(clientName, type));
    myCodeStyleManager.reformat(myActivity);
    String comment = String.format(COMMENT_FOR_FIELD, "");
    myActivity.addBefore(myFactory.createCommentFromText(comment, null), clientField);
    generateGoogleApiClientInitializationInOnCreate(clientName);
    return clientName;
  }

  /**
   * Generates GoogleApiClient initialization in onCreate method.
   * Used when there is no initializing statement before.
   *
   * @param clientName The GoogleApiClient name.
   */
  private void generateGoogleApiClientInitializationInOnCreate(@NotNull String clientName) {
    if (myOnCreate == null) {
      String onCreateMethod =
        String.format(ON_CREATE_FORMAT, clientName, myImportClasses.get(CLASS_GOOGLE_API_CLIENT), myImportClasses.get(CLASS_APP_INDEX));
      PsiMethod newOnCreate = myFactory.createMethodFromText(onCreateMethod, null);
      myActivity.add(newOnCreate);
    }
    else {
      String initText =
        String.format(CLIENT_FORMAT, clientName, myImportClasses.get(CLASS_GOOGLE_API_CLIENT), myImportClasses.get(CLASS_APP_INDEX));
      PsiElement initStatement = myOnCreate.add(myFactory.createStatementFromText(initText, null));
      addCommentsBefore(COMMENT_IN_JAVA, myOnCreate, initStatement);
    }
  }

  /**
   * Generates app indexing api calls (GoogleApiClient's connect & start) in onStart method.
   *
   * @param clientName     The GoogleApiClient name.
   * @param getActionMethodCallText The text of method call for get action.
   */
  private void addOrMergeOnStart(@NotNull String clientName, @NotNull String getActionMethodCallText) {
    if (myOnStart == null) {
      String onStartMethod = String.format(ON_START_FORMAT, clientName, getActionMethodCallText, myImportClasses.get(CLASS_APP_INDEX));
      myActivity.add(myFactory.createMethodFromText(onStartMethod, null));
    }
    else {
      String connectCall = clientName + ".connect();";
      List<PsiStatement> connectStatements = StatementFilter.filterCodeBlock(connectCall, myOnStart);
      // Creates connect() if needed. It should be on the top.
      if (connectStatements.isEmpty()) {
        PsiStatement connectStatement = myFactory.createStatementFromText(connectCall, null);
        List<PsiStatement> superOnStartStatements = StatementFilter.filterCodeBlock("super.onStart();", myOnStart);
        if (!superOnStartStatements.isEmpty()) {
          // Adds connect() statement after "super.onStart();".
          connectStatement = (PsiStatement)myOnStart.addAfter(connectStatement, superOnStartStatements.get(0));
          addCommentsBefore(COMMENT_IN_JAVA, myOnStart, connectStatement);
        }
        else {
          // Adds connect() statement after "{" in the code block.
          connectStatement = (PsiStatement)myOnStart.addAfter(connectStatement, myOnStart.getFirstBodyElement());
          addCommentsBefore(COMMENT_IN_JAVA, myOnStart, connectStatement);
        }
      }
      String startTextHalf = String.format(APP_INDEXING_START_HALF, clientName);
      myStartStatements = StatementFilter.filterStatements(startTextHalf, myStartStatements);
      String viewText = String.format(APP_INDEXING_VIEW, clientName);
      myViewStatements = StatementFilter.filterStatements(viewText, myViewStatements);
      // Creates Action variable and AppIndex.AppIndexApi.start() at the bottom.
      if (myStartStatements.isEmpty() && myViewStatements.isEmpty()) {
        String startText = String.format(APP_INDEXING_START, clientName, getActionMethodCallText, myImportClasses.get(CLASS_APP_INDEX));
        PsiElement startStatement = myFactory.createStatementFromText(startText, null);
        startStatement = myOnStart.add(startStatement);
        addCommentsBefore(COMMENT_IN_JAVA, myOnStart, startStatement);
      }
    }
  }

  /**
   * Generates app indexing api calls (GoogleApiClient's disconnect & end) in onStop method.
   *
   * @param clientName     The GoogleApiClient name.
   * @param getActionMethodCallText The text of method call for get action.
   */
  private void addOrMergeOnStop(@NotNull String clientName, @NotNull String getActionMethodCallText) {
    if (myOnStop == null) {
      String onStopMethod = String.format(ON_STOP_FORMAT, clientName, getActionMethodCallText, myImportClasses.get(CLASS_APP_INDEX));
      myActivity.add(myFactory.createMethodFromText(onStopMethod, null));
    }
    else {
      String disconnectCall = clientName + ".disconnect();";
      List<PsiStatement> disconnectStatements = StatementFilter.filterCodeBlock(disconnectCall, myOnStop);
      // Creates disconnect() if needed. It should be at the bottom.
      if (disconnectStatements.isEmpty()) {
        PsiElement disconnectStatement = myOnStop.add(myFactory.createStatementFromText(disconnectCall, null));
        addCommentsBefore(COMMENT_IN_JAVA, myOnStop, disconnectStatement);
      }
      String endTextHalf = String.format(APP_INDEXING_END_HALF, clientName);
      myEndStatements = StatementFilter.filterStatements(endTextHalf, myEndStatements);
      String viewEndText = String.format(APP_INDEXING_VIEWEND, clientName);
      myViewEndStatements = StatementFilter.filterStatements(viewEndText, myViewEndStatements);
      // Creates Action variable and AppIndex.AppIndexApi.end() on the top.
      if (myEndStatements.isEmpty() && myViewEndStatements.isEmpty()) {
        String endText = String.format(APP_INDEXING_END, clientName, getActionMethodCallText, myImportClasses.get(CLASS_APP_INDEX));
        PsiStatement endStatement = myFactory.createStatementFromText(endText, null);
        List<PsiStatement> superOnStopStatements = StatementFilter.filterCodeBlock("super.onStop();", myOnStop);
        if (!superOnStopStatements.isEmpty()) {
          // after "super.onStop();"
          endStatement = (PsiStatement)myOnStop.addAfter(endStatement, superOnStopStatements.get(0));
          addCommentsBefore(COMMENT_IN_JAVA, myOnStop, endStatement);
        }
        else {
          // after "{" in the code block.
          endStatement = (PsiStatement)myOnStop.addAfter(endStatement, myOnStop.getFirstBodyElement());
          addCommentsBefore(COMMENT_IN_JAVA, myOnStop, endStatement);
        }
      }
    }
  }

  /**
   * Compares two versions in the form of "12.3.456" etc.
   *
   * @return < 0 if version1 < version2; = 0 if version1 = version2; > 0 if version1 > version2
   */
  private static int compareVersion(@NotNull String version1, @NotNull String version2) {
    GradleCoordinate coordinate1 = GradleCoordinate.parseVersionOnly(version1);
    GradleCoordinate coordinate2 = GradleCoordinate.parseVersionOnly(version2);
    return GradleCoordinate.COMPARE_PLUS_HIGHER.compare(coordinate1, coordinate2);
  }

  /**
   * Gets the GMS meta-data tag in the application tag.
   */
  @Nullable
  private static XmlTag getGmsTag(@NotNull XmlTag application) {
    XmlTag[] children = application.getSubTags();
    for (XmlTag child : children) {
      if (child.getName().equalsIgnoreCase(TAG_METADATA)) {
        String tagName = child.getAttributeValue(SdkConstants.ATTR_NAME, SdkConstants.ANDROID_URI);
        if (tagName != null && tagName.equals(ATTR_NAME_METADATA_GMS)) {
          return child;
        }
      }
    }
    return null;
  }

  /**
   * Gets the client name in an app indexing API call statement.
   */
  @Nullable
  private static String getClientInAppIndexingApi(@NotNull PsiStatement statement) {
    if (statement instanceof PsiExpressionStatement) {
      // In the form of "AppIndex.AppIndexApi.start(mClient, viewAction);".
      PsiElement[] children = statement.getChildren();
      for (PsiElement child : children) {
        if (child instanceof PsiMethodCallExpression) {
          String callExpression = ((PsiMethodCallExpression)child).getMethodExpression().getText();
          callExpression = CharMatcher.WHITESPACE.removeFrom(callExpression);
          PsiType[] argsType = ((PsiMethodCallExpression)child).getArgumentList().getExpressionTypes();
          // API start / end has 2 arguments, viewEnd has 3 arguments, and view has 2.
          // The first arg is GoogleApiClient. If not declared before used, it has a null type.
          if ((callExpression.startsWith("AppIndex.AppIndexApi.") ||
               callExpression.startsWith("AppIndexApi") ||
               callExpression.startsWith(CLASS_APP_INDEX_FULL)) &&
              (argsType.length == 2 || argsType.length == 3 || argsType.length == 6) &&
              argsType[0] != null) {
            PsiExpression[] args = ((PsiMethodCallExpression)child).getArgumentList().getExpressions();
            String clientName = args[0].getText();
            if (clientName != null) {
              return clientName;
            }
          }
        }
      }
    }
    else if (statement instanceof PsiDeclarationStatement) {
      // In form of "PendingResult<Status> a = AppIndex.AppIndexApi.start(mClient, viewAction);".
      PsiElement[] children = ((PsiDeclarationStatement)statement).getDeclaredElements();
      for (PsiElement child : children) {
        if (child instanceof PsiVariable) {
          PsiExpression initializer = ((PsiVariable)child).getInitializer();
          if (initializer != null) {
            // Initializer is in the form of "AppIndex.AppIndexApi.start(mClient, viewAction)".
            PsiElement[] initChildren = initializer.getChildren();
            if (initChildren.length == 2 &&
                initChildren[0] instanceof PsiReferenceExpression &&
                initChildren[1] instanceof PsiExpressionList) {
              // initChildren[0] should be in the form of "AppIndex.AppIndexApi.start".
              // initChildren[1] should be in the form of "(mClient, ...)".
              // args should be in the form of {"mClient", ...}. Check its length and type.
              String referenceExpression = CharMatcher.WHITESPACE.removeFrom(initChildren[0].getText());
              PsiExpression[] args = ((PsiExpressionList)initChildren[1]).getExpressions();
              // API start / end has 2 arguments, viewEnd has 3 arguments, and view has 2.
              // The first arg is GoogleApiClient. If not declared before used, it has a null type.
              if ((referenceExpression.startsWith("AppIndex.AppIndexApi.") ||
                   referenceExpression.startsWith("AppIndexApi.") ||
                   referenceExpression.startsWith(CLASS_APP_INDEX_FULL)) &&
                  (args.length == 2 || args.length == 3 || args.length == 6) && args[0].getType() != null) {
                String clientName = args[0].getText();
                if (clientName != null) {
                  return clientName;
                }
              }
            }
          }
        }
      }
    }
    return null;
  }

  /**
   * Generates a name which has not been used.
   * Example: if "name" is used, "name2" will be returned;
   * if "name2" is also used, "name3" will be returned; ...
   *
   * @param name The initial default name.
   * @return A name based on the initial name which has not been used.
   */
  @NotNull
  private String getUnusedName(String name, VariableKind kind) {
    JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(myProject);
    name = javaCodeStyleManager.suggestVariableName(kind, name, null, null).names[0];

    Set<String> usedName = getUsedVariableName();
    String unusedName = name;
    int suffix = 2;
    while (usedName.contains(unusedName)) {
      unusedName = name + suffix;
      suffix++;
    }
    return unusedName;
  }

  /**
   * Generates GoogleApiClient initializing string.
   *
   * @param statementText The original initialize string.
   * @return The new string.
   */
  @Nullable
  private String generateApiClientInitializeString(@NotNull String statementText) {
    int splitPoint = statementText.lastIndexOf(".build()");
    if (!statementText.contains(String.format(BUILDER_APPINDEXAPI, CLASS_APP_INDEX_FULL)) &&
        !statementText.contains(String.format(BUILDER_APPINDEXAPI, CLASS_APP_INDEX)) && splitPoint != -1) {
      return statementText.substring(0, splitPoint) +
             String.format(BUILDER_APPINDEXAPI, myImportClasses.get(CLASS_APP_INDEX)) +
             statementText.substring(splitPoint);
    }
    else if (splitPoint != -1) {
      return statementText;
    }
    return null;
  }

  /**
   * Returns deep links of current activity in AndroidManifest.xml.
   */
  @Nullable
  @VisibleForTesting
  String getDeepLinkOfActivity() {
    XmlFile manifest = ManifestUtils.getAndroidManifestPsi(myModule);
    if (manifest != null && manifest.getRootTag() != null) {
      List<XmlTag> activityTags = ManifestUtils.searchXmlTagsByName(manifest.getRootTag(), SdkConstants.TAG_ACTIVITY);
      for (XmlTag activityTag : activityTags) {
        String activityName = activityTag.getAttributeValue(SdkConstants.ATTR_NAME, SdkConstants.ANDROID_URI);
        if (activityName != null && activityName.equals("." + myActivity.getName())) {
          List<String> deepLinks = DeepLinkUtils.getAllDeepLinks(activityTag);
          if (!deepLinks.isEmpty()) {
            return deepLinks.get(0);
          }
        }
      }
    }
    return null;
  }

  /**
   * Creates xml comment element.
   *
   * @param text The text form of comment.
   * @return The created comment.
   */
  @Nullable
  private XmlComment createXmlComment(@NotNull String text) {
    // XmlElementFactory does not provide API for creating comment.
    // So we create a tag wrapping the comment, and extract comment from the created tag.
    XmlElementFactory xmlElementFactory = XmlElementFactory.getInstance(myProject);
    XmlTag commentElement = xmlElementFactory.createTagFromText("<foo>" + text + "</foo>", XMLLanguage.INSTANCE);
    return PsiTreeUtil.getChildOfType(commentElement, XmlComment.class);
  }

  /**
   * Adds comments before a specific psi element.
   *
   * @param texts   The text of the comments.
   *                "// Comment1.
   *                // Comment2." are 2 comments.
   *                Factory cannot create 2 comments together, so we split them into list of comment texts.
   * @param element The psi element for adding comment in.
   * @param anchor  The psi element the added comment is anchored before.
   */
  private void addCommentsBefore(@NotNull List<String> texts, @NotNull PsiElement element, @NotNull PsiElement anchor) {
    myCodeStyleManager.reformat(element);
    for (String text : texts) {
      element.addBefore(myFactory.createCommentFromText(text, null), anchor);
      myCodeStyleManager.reformat(element);
    }
  }

  /**
   * Unlocks the file locked by PSI operation, so that the project can sync.
   *
   * @param file The file locked by PSI operation.
   */
  private void unlockFromPsiOperation(@NotNull PsiFile file) {
    Document doc = PsiDocumentManager.getInstance(myProject).getDocument(file);
    if (doc != null) {
      PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(doc);
    }
  }

  /**
   * Gets the surrounding class, if it inherits from a particular super class.
   *
   * @param element        The PsiElement for query.
   * @param inheritedClass the name of the class to inherit from
   * @return The surrounding class that meet the inheriting requirement.
   */
  @Nullable
  private static PsiClass getSurroundingInheritingClass(@NotNull PsiElement element, @NotNull String inheritedClass) {
    while (element != null) {
      if (element instanceof PsiClass) {
        PsiClass psiClass = (PsiClass)element;
        if (InheritanceUtil.isInheritor(psiClass, inheritedClass)) {
          return psiClass;
        }
      }
      if (element instanceof PsiFile) {
        return null;
      }
      element = element.getParent();
    }
    return null;
  }

  /**
   * Gets the body of the method in a specific class, given the method name.
   *
   * @param name               The method name.
   * @param parametersTypeName The type name of the parameters in the specific method.
   * @param psiClass           The class to find method in.
   * @return The code block body of the method, which will be null if no method is found with designated name or parameters.
   */
  @Nullable
  public static PsiCodeBlock getMethodBodyByName(@NotNull String name,
                                                 @NotNull List<String> parametersTypeName,
                                                 @NotNull PsiClass psiClass) {
    PsiMethod[] psiMethods = psiClass.findMethodsByName(name, false);
    for (PsiMethod psiMethod : psiMethods) {
      PsiType[] types = psiMethod.getSignature(PsiSubstitutor.EMPTY).getParameterTypes();
      if (types.length != parametersTypeName.size()) {
        continue;
      }
      boolean correctSignature = true;
      for (int i = 0; i < types.length; i++) {
        if (!types[i].getCanonicalText().equals(parametersTypeName.get(i))) {
          correctSignature = false;
          break;
        }
      }
      if (correctSignature) {
        return psiMethod.getBody();
      }
    }
    return null;
  }

  /**
   * Gets names of class members, given the type name.
   *
   * @param typeName The type presentable name.
   * @return The members' names
   */
  @NotNull
  private List<String> getFieldNameByType(@NotNull String typeName) {
    List<String> result = Lists.newArrayList();
    PsiField[] psiFields = myActivity.getFields();
    for (PsiField psiField : psiFields) {
      if (psiField.getType().getPresentableText().equals(typeName)) {
        result.add(psiField.getName());
      }
    }
    return result;
  }

  @Nullable
  private PsiField getFieldByName(@NotNull String name) {
    PsiField[] psiFields = myActivity.getFields();
    for (PsiField psiField : psiFields) {
      if (psiField.getName().equals(name)) {
        return psiField;
      }
    }
    return null;
  }

  /**
   * Inserts a single import statement.
   *
   * @param className The name of the import class.
   */
  private void insertSingleImportIfNeeded(@NotNull String className) {
    PsiImportList importList = ((PsiJavaFile)myFile).getImportList();
    if (importList != null && !hasImportStatement(importList, className)) {
      String dummyFileName = "_Dummy_" + className + "_." + JavaFileType.INSTANCE.getDefaultExtension();
      PsiJavaFile aFile = (PsiJavaFile)PsiFileFactory.getInstance(myProject)
        .createFileFromText(dummyFileName, JavaFileType.INSTANCE, "import " + className + ";");
      PsiImportList dummyImportList = aFile.getImportList();
      if (dummyImportList != null) {
        PsiImportStatement[] statements = dummyImportList.getImportStatements();
        PsiImportStatement statement = (PsiImportStatement)myCodeStyleManager.reformat(statements[0]);
        importList.add(statement);
      }
    }
  }

  /**
   * If an class has been imported in the importList.
   *
   * @param importList The import list.
   * @param className  The name of the class to be imported.
   * @return True if an class has been imported.
   */
  public static boolean hasImportStatement(@NotNull PsiImportList importList, @NotNull String className) {
    String packageName = className.substring(0, className.lastIndexOf('.'));
    PsiImportStatement singleImport = importList.findSingleClassImportStatement(className);
    PsiImportStatement onDemandImport = importList.findOnDemandImportStatement(packageName);
    return singleImport != null || onDemandImport != null;
  }

  /**
   * Returns all the fields' and local variables' names which have already been used.
   */
  @NotNull
  private Set<String> getUsedVariableName() {
    Set<String> usedNames = Sets.newHashSet();
    // name of PsiFields in PsiClass
    PsiField[] psiFields = myActivity.getFields();
    for (PsiField psiField : psiFields) {
      usedNames.add(psiField.getName());
    }
    // name of PsiLocalVariables in PsiMethods in PsiClass
    PsiMethod[] psiMethods = myActivity.getMethods();
    for (PsiMethod psiMethod : psiMethods) {
      PsiCodeBlock methodBody = psiMethod.getBody();
      if (methodBody != null) {
        List<PsiStatement> psiStatements = StatementFilter.filterCodeBlock("", methodBody);
        for (PsiStatement psiStatement : psiStatements) {
          if (psiStatement instanceof PsiDeclarationStatement) {
            PsiElement[] declaredElements = ((PsiDeclarationStatement)psiStatement).getDeclaredElements();
            for (PsiElement declaredElement : declaredElements) {
              usedNames.add(((PsiLocalVariable)declaredElement).getName());
            }
          }
        }
      }
    }
    return usedNames;
  }

  static class ApiCreatorException extends Exception {
    public ApiCreatorException(String message) {
      super(message);
    }
  }
}
