/*
 * 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.android.tools.idea.startup;

import static com.android.tools.idea.io.FilePaths.toSystemDependentPath;
import static com.intellij.openapi.actionSystem.IdeActions.ACTION_COMPILE;
import static com.intellij.openapi.actionSystem.IdeActions.ACTION_COMPILE_PROJECT;
import static com.intellij.openapi.actionSystem.IdeActions.ACTION_MAKE_MODULE;
import static com.intellij.openapi.util.io.FileUtil.join;
import static com.intellij.openapi.util.text.StringUtil.isEmpty;

import com.android.tools.analytics.AnalyticsSettings;
import com.android.tools.analytics.UsageTracker;
import com.android.tools.idea.actions.CreateClassAction;
import com.android.tools.idea.actions.MakeIdeaModuleAction;
import com.android.tools.idea.analytics.IdeBrandProviderKt;
import com.android.tools.idea.flags.StudioFlags;
import com.android.tools.idea.run.deployment.RunOnMultipleDevicesAction;
import com.android.tools.idea.run.deployment.SelectMultipleDevicesAction;
import com.android.tools.idea.serverflags.ServerFlagDownloader;
import com.android.tools.idea.serverflags.ServerFlagInitializer;
import com.android.tools.idea.stats.AndroidStudioUsageTracker;
import com.android.tools.idea.stats.GcPauseWatcher;
import com.android.tools.idea.testartifacts.junit.AndroidJUnitConfigurationProducer;
import com.android.tools.idea.testartifacts.junit.AndroidJUnitConfigurationType;
import com.intellij.analytics.AndroidStudioAnalytics;
import com.intellij.concurrency.JobScheduler;
import com.intellij.execution.actions.RunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.junit.JUnitConfigurationProducer;
import com.intellij.execution.junit.JUnitConfigurationType;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.impl.ActionConfigurationCustomizer;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.XmlHighlighterColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.AppUIUtil;
import java.io.File;
import java.util.concurrent.ScheduledExecutorService;
import org.intellij.plugins.intelliLang.inject.groovy.GrConcatenationInjector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension;
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverExtension;

/**
 * Performs Android Studio specific initialization tasks that are build-system-independent.
 * <p>
 * <strong>Note:</strong> Do not add any additional tasks unless it is proven that the tasks are common to all IDEs. Use
 * {@link GradleSpecificInitializer} instead.
 * </p>
 */
public class AndroidStudioInitializer implements ActionConfigurationCustomizer {

  @Override
  public void customize(@NotNull ActionManager actionManager) {
    checkInstallation();
    setUpNewFilePopupActions(actionManager);
    setUpMakeActions(actionManager);
    disableGroovyLanguageInjection();

    if (StudioFlags.CUSTOM_JAVA_NEW_CLASS_DIALOG.get()) {
      replaceNewClassDialog(actionManager);
    }

    ServerFlagInitializer.initializeService();
    ScheduledExecutorService scheduler = JobScheduler.getScheduler();
    scheduler.execute(ServerFlagDownloader::downloadServerFlagList);

    setupAnalytics();
    disableIdeaJUnitConfigurations(actionManager);
    disableKaptImportHandlers();
    hideRarelyUsedIntellijActions(actionManager);
    setupResourceManagerActions(actionManager);
    if (StudioFlags.TWEAK_COLOR_SCHEME.get()) {
      tweakDefaultColorScheme();
    }

    setUpDeviceComboBoxActions(actionManager);
  }

  private static void tweakDefaultColorScheme() {
    // Modify built-in "Default" color scheme to remove background from XML tags.
    // "Darcula" and user schemes will not be touched.
    EditorColorsScheme colorsScheme = EditorColorsManager.getInstance().getScheme(EditorColorsScheme.DEFAULT_SCHEME_NAME);
    TextAttributes textAttributes = colorsScheme.getAttributes(HighlighterColors.TEXT);
    TextAttributes xmlTagAttributes = colorsScheme.getAttributes(XmlHighlighterColors.XML_TAG);
    xmlTagAttributes.setBackgroundColor(textAttributes.getBackgroundColor());
  }

  private static void setUpDeviceComboBoxActions(@NotNull ActionManager manager) {
    String id = StudioFlags.RUN_ON_MULTIPLE_DEVICES_ACTION_ENABLED.get() ? SelectMultipleDevicesAction.ID : RunOnMultipleDevicesAction.ID;
    Actions.hideAction(manager, id);
  }

  private static void setupResourceManagerActions(ActionManager actionManager) {
    Actions.hideAction(actionManager, "Images.ShowThumbnails");
    // Move the ShowServicesAction to the end of the queue by re-registering it, since it will always consume the shortcut event.
    // TODO(144579193): Remove this workaround when it's no longer necessary.
    //  Eg: When ShowServicesAction can decide whether it's enabled or not.
    AnAction servicesAction = actionManager.getAction("ServiceView.ShowServices");
    Actions.replaceAction(actionManager, "ServiceView.ShowServices", servicesAction);
  }

  /*
   * sets up collection of Android Studio specific analytics.
   */
  private static void setupAnalytics() {
    AndroidStudioAnalytics.getInstance().initializeAndroidStudioUsageTrackerAndPublisher();

    // If the user hasn't opted in, we will ask IJ to check if the user has
    // provided a decision on the statistics consent. If the user hasn't made a
    // choice, a modal dialog will be shown asking for a decision
    // before the regular IDE ui components are shown.
    if (!AnalyticsSettings.getOptedIn()) {
      Application application = ApplicationManager.getApplication();
      // If we're running in a test or headless mode, do not show the dialog
      // as it would block the test & IDE from proceeding.
      // NOTE: in this case the metrics logic will be left in the opted-out state
      // and no metrics are ever sent.
      if (!application.isUnitTestMode() && !application.isHeadlessEnvironment() &&
          !Boolean.getBoolean("disable.android.analytics.consent.dialog.for.test")) {
        ApplicationManager.getApplication().invokeLater(() -> AppUIUtil.showConsentsAgreementIfNeeded(getLog()));
      }
    }

    ApplicationInfo application = ApplicationInfo.getInstance();
    UsageTracker.setVersion(application.getStrictVersion());
    UsageTracker.setIdeBrand(IdeBrandProviderKt.currentIdeBrand());
    if (ApplicationManager.getApplication().isInternal()) {
      UsageTracker.setIdeaIsInternal(true);
    }
    AndroidStudioUsageTracker.setup(JobScheduler.getScheduler());
    new GcPauseWatcher();
  }

  private static void checkInstallation() {
    String studioHome = PathManager.getHomePath();
    if (isEmpty(studioHome)) {
      getLog().info("Unable to find Studio home directory");
      return;
    }
    File studioHomePath = toSystemDependentPath(studioHome);
    if (!studioHomePath.isDirectory()) {
      getLog().info(String.format("The path '%1$s' does not belong to an existing directory", studioHomePath.getPath()));
      return;
    }
    File androidPluginLibFolderPath = new File(studioHomePath, join("plugins", "android", "lib"));
    if (!androidPluginLibFolderPath.isDirectory()) {
      getLog().info(String.format("The path '%1$s' does not belong to an existing directory", androidPluginLibFolderPath.getPath()));
      return;
    }

    // Look for signs that the installation is corrupt due to improper updates (typically unzipping on top of previous install)
    // which doesn't delete files that have been removed or renamed
    if (new File(studioHomePath, join("plugins", "android-designer")).exists()) {
      String msg = "Your Android Studio installation is corrupt and will not work properly.\n" +
                   "(Found plugins/android-designer which should not be present.)\n" +
                   "This usually happens if Android Studio is extracted into an existing older version.\n\n" +
                   "Please reinstall (and make sure the new installation directory is empty first.)";
      String title = "Corrupt Installation";
      int option = Messages.showDialog(msg, title, new String[]{"Quit", "Proceed Anyway"}, 0, Messages.getErrorIcon());
      if (option == 0) {
        ApplicationManager.getApplication().exit();
      }
    }
  }

  // Remove popup actions that we don't use
  private static void setUpNewFilePopupActions(ActionManager actionManager) {
    Actions.hideAction(actionManager, "NewHtmlFile");
    Actions.hideAction(actionManager, "NewPackageInfo");

    // Hide designer actions
    Actions.hideAction(actionManager, "NewForm");
    Actions.hideAction(actionManager, "NewDialog");
    Actions.hideAction(actionManager, "NewFormSnapshot");

    // Hide individual actions that aren't part of a group
    Actions.hideAction(actionManager, "Groovy.NewClass");
    Actions.hideAction(actionManager, "Groovy.NewScript");
  }

  // The original actions will be visible only on plain IDEA projects.
  private static void setUpMakeActions(ActionManager actionManager) {
    // 'Build' > 'Make Project' action
    Actions.hideAction(actionManager, "CompileDirty");

    // 'Build' > 'Make Modules' action
    // We cannot simply hide this action, because of a NPE.
    Actions.replaceAction(actionManager, ACTION_MAKE_MODULE, new MakeIdeaModuleAction());

    // 'Build' > 'Rebuild' action
    Actions.hideAction(actionManager, ACTION_COMPILE_PROJECT);

    // 'Build' > 'Compile Modules' action
    Actions.hideAction(actionManager, ACTION_COMPILE);
  }

  // Fix https://code.google.com/p/android/issues/detail?id=201624
  private static void disableGroovyLanguageInjection() {
    ApplicationManager.getApplication().getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
      @Override
      public void projectOpened(@NotNull Project project) {
        ExtensionPoint<MultiHostInjector> extensionPoint = MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME.getPoint(project);
        for (MultiHostInjector injector : extensionPoint.getExtensions()) {
          if (injector instanceof GrConcatenationInjector) {
            extensionPoint.unregisterExtension(injector.getClass());
            return;
          }
        }

        getLog().info("Failed to disable 'org.intellij.plugins.intelliLang.inject.groovy.GrConcatenationInjector'");
      }
    });
  }

  private static void replaceNewClassDialog(ActionManager actionManager) {
    Actions.replaceAction(actionManager, "NewClass", new CreateClassAction());

    // Update the text for the file creation templates.
    FileTemplateManager fileTemplateManager = FileTemplateManager.getDefaultInstance();
    for (String templateName : new String[]{"Singleton", "Class", "Interface", "Enum", "AnnotationType"}) {
      FileTemplate template = fileTemplateManager.getInternalTemplate(templateName);
      template.setText(fileTemplateManager.getJ2eeTemplate(templateName).getText());
    }
  }

  private static void disableKaptImportHandlers() {
    ExtensionPoint<GradleProjectResolverExtension> resolverExtensionPoint = GradleProjectResolverExtension.EP_NAME.getPoint();
    resolverExtensionPoint.unregisterExtension(KaptProjectResolverExtension.class);
  }

  // JUnit original Extension JUnitConfigurationType is disabled so it can be replaced by its child class AndroidJUnitConfigurationType
  private static void disableIdeaJUnitConfigurations(ActionManager actionManager) {
    // First we unregister the ConfigurationProducers, and after the ConfigurationType

    //noinspection rawtypes: RunConfigurationProducer.EP_NAME uses raw types.
    ExtensionPoint<RunConfigurationProducer> configurationProducerExtensionPoint = RunConfigurationProducer.EP_NAME.getPoint();
    //noinspection rawtypes: RunConfigurationProducer.EP_NAME uses raw types.
    for (RunConfigurationProducer runConfigurationProducer : configurationProducerExtensionPoint.getExtensions()) {
      if (runConfigurationProducer instanceof JUnitConfigurationProducer
          && !(runConfigurationProducer instanceof AndroidJUnitConfigurationProducer)) {
        // In AndroidStudio these ConfigurationProducer s are replaced
        configurationProducerExtensionPoint.unregisterExtension(runConfigurationProducer.getClass());
      }
    }

    ExtensionPoint<ConfigurationType> configurationTypeExtensionPoint = ConfigurationType.CONFIGURATION_TYPE_EP.getPoint();
    for (ConfigurationType configurationType : configurationTypeExtensionPoint.getExtensions()) {
      if (configurationType instanceof JUnitConfigurationType && !(configurationType instanceof AndroidJUnitConfigurationType)) {
        // In Android Studio the user is forced to use AndroidJUnitConfigurationType instead of JUnitConfigurationType
        configurationTypeExtensionPoint.unregisterExtension(configurationType.getClass());
      }
    }

    // We hide actions registered by the JUnit plugin and instead we use those registered in android-junit.xml
    Actions.hideAction(actionManager, "excludeFromSuite");
    Actions.hideAction(actionManager, "AddToISuite");
  }

  private static void hideRarelyUsedIntellijActions(ActionManager actionManager) {
    // Hide the Save File as Template action due to its rare use in Studio.
    Actions.hideAction(actionManager, "SaveFileAsTemplate");
  }

  @NotNull
  private static Logger getLog() {
    return Logger.getInstance(AndroidStudioInitializer.class);
  }
}
