/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.idea.blaze.plugin.run;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.idea.blaze.base.command.BlazeCommand;
import com.google.idea.blaze.base.command.BlazeCommandName;
import com.google.idea.blaze.base.command.BlazeFlags;
import com.google.idea.blaze.base.ideinfo.Dependency;
import com.google.idea.blaze.base.ideinfo.Dependency.DependencyType;
import com.google.idea.blaze.base.ideinfo.JavaIdeInfo;
import com.google.idea.blaze.base.ideinfo.LibraryArtifact;
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.TargetExpression;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.run.BlazeConfigurationNameBuilder;
import com.google.idea.blaze.base.run.BlazeRunConfiguration;
import com.google.idea.blaze.base.run.state.RunConfigurationFlagsState;
import com.google.idea.blaze.base.run.state.RunConfigurationStateEditor;
import com.google.idea.blaze.base.run.targetfinder.TargetFinder;
import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
import com.google.idea.blaze.base.ui.UiUtil;
import com.google.idea.blaze.plugin.IntellijPluginRule;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.JavaCommandLineState;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.LocatableConfigurationBase;
import com.intellij.execution.configurations.LogFileOptions;
import com.intellij.execution.configurations.ModuleRunConfiguration;
import com.intellij.execution.configurations.ParametersList;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.application.JetBrainsProtocolHandler;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.ui.configuration.JdkComboBox;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.RawCommandLineEditor;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.PlatformUtils;
import java.awt.BorderLayout;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import org.jdom.Element;

/**
 * A run configuration that builds a plugin jar via blaze, copies it to the SDK sandbox, then runs
 * IJ with the plugin loaded.
 */
public class BlazeIntellijPluginConfiguration extends LocatableConfigurationBase
    implements BlazeRunConfiguration, ModuleRunConfiguration {

  private static final String TARGET_TAG = "blaze-target";
  private static final String USER_BLAZE_FLAG_TAG = "blaze-user-flag";
  private static final String USER_EXE_FLAG_TAG = "blaze-user-exe-flag";
  private static final String SDK_ATTR = "blaze-plugin-sdk";
  private static final String VM_PARAMS_ATTR = "blaze-vm-params";
  private static final String PROGRAM_PARAMS_ATTR = "blaze-program-params";
  private static final String KEEP_IN_SYNC_TAG = "keep-in-sync";

  private final String buildSystem;

  @Nullable private Label target;
  private final RunConfigurationFlagsState blazeFlags;
  private final RunConfigurationFlagsState exeFlags;
  @Nullable private Sdk pluginSdk;
  @Nullable String vmParameters;
  @Nullable private String programParameters;

  // for keeping imported configurations in sync with their source XML
  @Nullable private Boolean keepInSync = null;

  public BlazeIntellijPluginConfiguration(
      Project project,
      ConfigurationFactory factory,
      String name,
      @Nullable TargetIdeInfo initialTarget) {
    super(project, factory, name);
    this.buildSystem = Blaze.buildSystemName(project);
    Sdk projectSdk = ProjectRootManager.getInstance(project).getProjectSdk();
    if (IdeaJdkHelper.isIdeaJdk(projectSdk)) {
      pluginSdk = projectSdk;
    }
    if (initialTarget != null) {
      target = initialTarget.key.label;
    }
    blazeFlags = new RunConfigurationFlagsState(USER_BLAZE_FLAG_TAG, buildSystem + " flags:");
    exeFlags = new RunConfigurationFlagsState(USER_EXE_FLAG_TAG, "Executable flags:");
  }

  @Override
  public void setKeepInSync(@Nullable Boolean keepInSync) {
    this.keepInSync = keepInSync;
  }

  @Override
  @Nullable
  public Boolean getKeepInSync() {
    return keepInSync;
  }

  @Override
  @Nullable
  public Label getTarget() {
    return target;
  }

  public void setTarget(Label target) {
    this.target = target;
  }

  public void setPluginSdk(Sdk sdk) {
    if (IdeaJdkHelper.isIdeaJdk(sdk)) {
      pluginSdk = sdk;
    }
  }

  @Override
  public ArrayList<LogFileOptions> getAllLogFiles() {
    ArrayList<LogFileOptions> result = new ArrayList<>();
    if (pluginSdk == null) {
      return result;
    }
    String sandboxHome = IdeaJdkHelper.getSandboxHome(pluginSdk);
    String logFile = Paths.get(sandboxHome, "system", "log", "idea.log").toString();
    LogFileOptions logFileOptions = new LogFileOptions("idea.log", logFile, true, true, true);
    result.add(logFileOptions);
    return result;
  }

  private ImmutableList<File> findPluginJars() throws ExecutionException {
    BlazeProjectData blazeProjectData =
        BlazeProjectDataManager.getInstance(getProject()).getBlazeProjectData();
    if (blazeProjectData == null) {
      throw new ExecutionException("Not synced yet, please sync project");
    }
    TargetIdeInfo target = TargetFinder.getInstance().targetForLabel(getProject(), getTarget());
    if (target == null) {
      throw new ExecutionException(
          buildSystem + " target '" + getTarget() + "' not imported during sync");
    }
    return IntellijPluginRule.isPluginBundle(target)
        ? findBundledJars(blazeProjectData.artifactLocationDecoder, target)
        : ImmutableList.of(findPluginJar(blazeProjectData.artifactLocationDecoder, target));
  }

  private ImmutableList<File> findBundledJars(
      ArtifactLocationDecoder artifactLocationDecoder, TargetIdeInfo target)
      throws ExecutionException {
    ImmutableList.Builder<File> jars = ImmutableList.builder();
    for (Dependency dep : target.dependencies) {
      if (dep.dependencyType == DependencyType.COMPILE_TIME && dep.targetKey.isPlainTarget()) {
        TargetIdeInfo depTarget =
            TargetFinder.getInstance().targetForLabel(getProject(), dep.targetKey.label);
        if (depTarget != null && IntellijPluginRule.isSinglePluginTarget(depTarget)) {
          jars.add(findPluginJar(artifactLocationDecoder, depTarget));
        }
      }
    }
    return jars.build();
  }

  private File findPluginJar(ArtifactLocationDecoder artifactLocationDecoder, TargetIdeInfo target)
      throws ExecutionException {
    JavaIdeInfo javaIdeInfo = target.javaIdeInfo;
    if (!IntellijPluginRule.isSinglePluginTarget(target) || javaIdeInfo == null) {
      throw new ExecutionException(
          buildSystem + " target '" + target + "' is not a valid intellij_plugin target");
    }
    Collection<LibraryArtifact> jars = javaIdeInfo.jars;
    if (javaIdeInfo.jars.size() > 1) {
      throw new ExecutionException("Invalid IntelliJ plugin target: it has multiple output jars");
    }
    LibraryArtifact artifact = jars.isEmpty() ? null : jars.iterator().next();
    if (artifact == null || artifact.classJar == null) {
      throw new ExecutionException("No output plugin jar found for '" + target + "'");
    }
    return artifactLocationDecoder.decode(artifact.classJar);
  }

  /**
   * Plugin jar has been previously created via blaze build. This method: - copies jar to sandbox
   * environment - cracks open jar and finds plugin.xml (with ID, etc., needed for JVM args) - sets
   * up the SDK, etc. (use project SDK?) - sets up the JVM, and returns a JavaCommandLineState
   */
  @Nullable
  @Override
  public RunProfileState getState(Executor executor, ExecutionEnvironment env)
      throws ExecutionException {
    final Sdk ideaJdk = pluginSdk;
    if (!IdeaJdkHelper.isIdeaJdk(ideaJdk)) {
      throw new ExecutionException("Choose an IntelliJ Platform Plugin SDK");
    }
    String sandboxHome = IdeaJdkHelper.getSandboxHome(ideaJdk);
    if (sandboxHome == null) {
      throw new ExecutionException("No sandbox specified for IntelliJ Platform Plugin SDK");
    }

    try {
      sandboxHome = new File(sandboxHome).getCanonicalPath();
    } catch (IOException e) {
      throw new ExecutionException("No sandbox specified for IntelliJ Platform Plugin SDK");
    }
    final String canonicalSandbox = sandboxHome;
    final ImmutableList<File> pluginJars = findPluginJars();
    for (File file : pluginJars) {
      if (!file.exists()) {
        throw new ExecutionException(
            String.format(
                "Plugin jar '%s' not found. Did the %s build fail?", file.getName(), buildSystem));
      }
    }
    // copy license from running instance of idea
    IdeaJdkHelper.copyIDEALicense(sandboxHome);

    final JavaCommandLineState state =
        new JavaCommandLineState(env) {
          @Override
          protected JavaParameters createJavaParameters() throws ExecutionException {
            String buildNumber = IdeaJdkHelper.getBuildNumber(ideaJdk);
            List<String> pluginIds = Lists.newArrayList();
            for (File jar : pluginJars) {
              pluginIds.add(copyPluginJarToSandbox(jar, buildNumber, canonicalSandbox));
            }

            final JavaParameters params = new JavaParameters();

            ParametersList vm = params.getVMParametersList();

            fillParameterList(vm, vmParameters);
            fillParameterList(params.getProgramParametersList(), programParameters);

            IntellijWithPluginClasspathHelper.addRequiredVmParams(params, ideaJdk);

            vm.defineProperty(
                JetBrainsProtocolHandler.REQUIRED_PLUGINS_KEY, Joiner.on(',').join(pluginIds));

            if (!vm.hasProperty(PlatformUtils.PLATFORM_PREFIX_KEY) && buildNumber != null) {
              String prefix = IdeaJdkHelper.getPlatformPrefix(buildNumber);
              if (prefix != null) {
                vm.defineProperty(PlatformUtils.PLATFORM_PREFIX_KEY, prefix);
              }
            }
            return params;
          }

          @Override
          protected OSProcessHandler startProcess() throws ExecutionException {
            final OSProcessHandler handler = super.startProcess();
            handler.addProcessListener(
                new ProcessAdapter() {
                  @Override
                  public void processTerminated(ProcessEvent event) {
                    for (File jar : pluginJars) {
                      pluginDestination(jar, canonicalSandbox).delete();
                    }
                  }
                });
            return handler;
          }
        };
    return state;
  }

  private static File pluginDestination(File jar, String sandboxPath) {
    return new File(sandboxPath, "plugins/" + jar.getName());
  }

  /** Copies the plugin jar to the sandbox, and returns the plugin ID. */
  private static String copyPluginJarToSandbox(File jar, String buildNumber, String sandboxPath)
      throws ExecutionException {
    IdeaPluginDescriptor pluginDescriptor = PluginManagerCore.loadDescriptor(jar, "plugin.xml");
    if (PluginManagerCore.isIncompatible(pluginDescriptor, BuildNumber.fromString(buildNumber))) {
      throw new ExecutionException(
          String.format(
              "Plugin SDK version '%s' is incompatible with this plugin "
                  + "(since: '%s', until: '%s')",
              buildNumber, pluginDescriptor.getSinceBuild(), pluginDescriptor.getUntilBuild()));
    }
    File pluginJarDestination = pluginDestination(jar, sandboxPath);
    try {
      pluginJarDestination.getParentFile().mkdirs();
      Files.copy(jar.toPath(), pluginJarDestination.toPath(), StandardCopyOption.REPLACE_EXISTING);
    } catch (IOException e) {
      throw new ExecutionException("Error copying plugin jar to sandbox", e);
    }
    return pluginDescriptor.getPluginId().getIdString();
  }

  private static void fillParameterList(ParametersList list, @Nullable String value) {
    if (value == null) {
      return;
    }

    for (String parameter : value.split(" ")) {
      if (parameter != null && parameter.length() > 0) {
        list.add(parameter);
      }
    }
  }

  @Override
  public Module[] getModules() {
    return Module.EMPTY_ARRAY;
  }

  @Override
  public void checkConfiguration() throws RuntimeConfigurationException {
    super.checkConfiguration();

    Label label = getTarget();
    if (label == null) {
      throw new RuntimeConfigurationError("Select a target to run");
    }
    TargetIdeInfo target = TargetFinder.getInstance().targetForLabel(getProject(), label);
    if (target == null) {
      throw new RuntimeConfigurationError("The selected target does not exist.");
    }
    if (!IntellijPluginRule.isPluginTarget(target)) {
      throw new RuntimeConfigurationError("The selected target is not an intellij_plugin");
    }
    if (!IdeaJdkHelper.isIdeaJdk(pluginSdk)) {
      throw new RuntimeConfigurationError("Select an IntelliJ Platform Plugin SDK");
    }
  }

  @Override
  public void readExternal(Element element) throws InvalidDataException {
    super.readExternal(element);
    // Target is persisted as a tag to permit multiple targets in the future.
    Element targetElement = element.getChild(TARGET_TAG);
    if (targetElement != null && !Strings.isNullOrEmpty(targetElement.getTextTrim())) {
      target = (Label) TargetExpression.fromString(targetElement.getTextTrim());
    } else {
      target = null;
    }
    blazeFlags.readExternal(element);
    exeFlags.readExternal(element);

    String sdkName = element.getAttributeValue(SDK_ATTR);
    if (!Strings.isNullOrEmpty(sdkName)) {
      pluginSdk = ProjectJdkTable.getInstance().findJdk(sdkName);
    }
    vmParameters = Strings.emptyToNull(element.getAttributeValue(VM_PARAMS_ATTR));
    programParameters = Strings.emptyToNull(element.getAttributeValue(PROGRAM_PARAMS_ATTR));

    String keepInSyncString = element.getAttributeValue(KEEP_IN_SYNC_TAG);
    keepInSync = keepInSyncString != null ? Boolean.parseBoolean(keepInSyncString) : null;
  }

  @Override
  public void writeExternal(Element element) throws WriteExternalException {
    super.writeExternal(element);
    if (target != null) {
      // Target is persisted as a tag to permit multiple targets in the future.
      Element targetElement = new Element(TARGET_TAG);
      targetElement.setText(target.toString());
      element.addContent(targetElement);
    }
    blazeFlags.writeExternal(element);
    exeFlags.writeExternal(element);
    if (pluginSdk != null) {
      element.setAttribute(SDK_ATTR, pluginSdk.getName());
    }
    if (vmParameters != null) {
      element.setAttribute(VM_PARAMS_ATTR, vmParameters);
    }
    if (programParameters != null) {
      element.setAttribute(PROGRAM_PARAMS_ATTR, programParameters);
    }
    if (keepInSync != null) {
      element.setAttribute(KEEP_IN_SYNC_TAG, Boolean.toString(keepInSync));
    }
  }

  @Override
  public BlazeIntellijPluginConfiguration clone() {
    final BlazeIntellijPluginConfiguration configuration =
        (BlazeIntellijPluginConfiguration) super.clone();
    configuration.target = target;
    configuration.blazeFlags.setFlags(blazeFlags.getFlags());
    configuration.exeFlags.setFlags(exeFlags.getFlags());
    configuration.pluginSdk = pluginSdk;
    configuration.vmParameters = vmParameters;
    configuration.programParameters = programParameters;
    configuration.keepInSync = keepInSync;
    return configuration;
  }

  protected BlazeCommand buildBlazeCommand(Project project, ProjectViewSet projectViewSet) {
    BlazeCommand.Builder command =
        BlazeCommand.builder(Blaze.getBuildSystem(getProject()), BlazeCommandName.BUILD)
            .addTargets(getTarget())
            .addBlazeFlags(BlazeFlags.buildFlags(project, projectViewSet))
            .addBlazeFlags(blazeFlags.getFlags())
            .addExeFlags(exeFlags.getFlags());
    return command.build();
  }

  @Override
  public BlazeIntellijPluginConfigurationSettingsEditor getConfigurationEditor() {
    List<TargetIdeInfo> javaTargets =
        TargetFinder.getInstance().findTargets(getProject(), IntellijPluginRule::isPluginTarget);
    List<Label> javaLabels = Lists.newArrayList();
    for (TargetIdeInfo target : javaTargets) {
      javaLabels.add(target.key.label);
    }
    return new BlazeIntellijPluginConfigurationSettingsEditor(
        javaLabels, blazeFlags.getEditor(getProject()), exeFlags.getEditor(getProject()));
  }

  @Override
  @Nullable
  public String suggestedName() {
    Label target = getTarget();
    if (target == null) {
      return null;
    }
    return new BlazeConfigurationNameBuilder()
        .setBuildSystemName(getProject())
        .setCommandName("build")
        .setTargetString(target)
        .build();
  }

  @VisibleForTesting
  static class BlazeIntellijPluginConfigurationSettingsEditor
      extends SettingsEditor<BlazeIntellijPluginConfiguration> {
    private final ComboBox<Label> targetCombo;
    private final RunConfigurationStateEditor blazeFlagsEditor;
    private final RunConfigurationStateEditor exeFlagsEditor;
    private final JdkComboBox sdkCombo;
    private final LabeledComponent<RawCommandLineEditor> vmParameters = new LabeledComponent<>();
    private final LabeledComponent<RawCommandLineEditor> programParameters =
        new LabeledComponent<>();
    private final JBCheckBox keepInSyncCheckBox;

    public BlazeIntellijPluginConfigurationSettingsEditor(
        List<Label> javaLabels,
        RunConfigurationStateEditor blazeFlagsEditor,
        RunConfigurationStateEditor exeFlagsEditor) {
      targetCombo =
          new ComboBox<>(
              new DefaultComboBoxModel<>(
                  Ordering.usingToString().sortedCopy(javaLabels).toArray(new Label[0])));
      targetCombo.setRenderer(
          new ListCellRendererWrapper<Label>() {
            @Override
            public void customize(
                JList list, @Nullable Label value, int index, boolean selected, boolean hasFocus) {
              setText(value == null ? null : value.toString());
            }
          });
      this.blazeFlagsEditor = blazeFlagsEditor;
      this.exeFlagsEditor = exeFlagsEditor;
      ProjectSdksModel sdksModel = new ProjectSdksModel();
      sdksModel.reset(null);
      sdkCombo = new JdkComboBox(sdksModel, IdeaJdkHelper::isIdeaJdkType);

      keepInSyncCheckBox = new JBCheckBox("Keep in sync with source XML");
      keepInSyncCheckBox.addItemListener(e -> updateEnabledStatus());
    }

    private void updateEnabledStatus() {
      setEnabled(!keepInSyncCheckBox.isVisible() || !keepInSyncCheckBox.isSelected());
    }

    private void setEnabled(boolean enabled) {
      targetCombo.setEnabled(enabled);
      sdkCombo.setEnabled(enabled);
      vmParameters.getComponent().setEnabled(enabled);
      programParameters.getComponent().setEnabled(enabled);
      blazeFlagsEditor.setComponentEnabled(enabled);
      exeFlagsEditor.setComponentEnabled(enabled);
    }

    @VisibleForTesting
    @Override
    public void resetEditorFrom(BlazeIntellijPluginConfiguration s) {
      targetCombo.setSelectedItem(s.getTarget());
      blazeFlagsEditor.resetEditorFrom(s.blazeFlags);
      exeFlagsEditor.resetEditorFrom(s.exeFlags);
      if (s.pluginSdk != null) {
        sdkCombo.setSelectedJdk(s.pluginSdk);
      } else {
        s.pluginSdk = sdkCombo.getSelectedJdk();
      }
      if (s.vmParameters != null) {
        vmParameters.getComponent().setText(s.vmParameters);
      }
      if (s.programParameters != null) {
        programParameters.getComponent().setText(s.programParameters);
      }
      keepInSyncCheckBox.setVisible(s.keepInSync != null);
      if (s.keepInSync != null) {
        keepInSyncCheckBox.setSelected(s.keepInSync);
      }
    }

    @VisibleForTesting
    @Override
    public void applyEditorTo(BlazeIntellijPluginConfiguration s) throws ConfigurationException {
      try {
        s.target = (Label) targetCombo.getSelectedItem();
      } catch (ClassCastException e) {
        throw new ConfigurationException("Invalid label specified.");
      }
      blazeFlagsEditor.applyEditorTo(s.blazeFlags);
      exeFlagsEditor.applyEditorTo(s.exeFlags);
      s.pluginSdk = sdkCombo.getSelectedJdk();
      s.vmParameters = vmParameters.getComponent().getText();
      s.programParameters = programParameters.getComponent().getText();
      s.keepInSync = keepInSyncCheckBox.isVisible() ? keepInSyncCheckBox.isSelected() : null;
    }

    @Override
    protected JComponent createEditor() {
      vmParameters.setText("VM options:");
      vmParameters.setComponent(new RawCommandLineEditor());
      vmParameters.getComponent().setDialogCaption(vmParameters.getRawText());
      vmParameters.setLabelLocation(BorderLayout.WEST);

      programParameters.setText("Program arguments");
      programParameters.setComponent(new RawCommandLineEditor());
      programParameters.getComponent().setDialogCaption(programParameters.getRawText());
      programParameters.setLabelLocation(BorderLayout.WEST);

      return UiUtil.createBox(
          new JLabel("Target:"),
          targetCombo,
          new JLabel("Plugin SDK"),
          sdkCombo,
          vmParameters.getLabel(),
          vmParameters.getComponent(),
          programParameters.getLabel(),
          programParameters.getComponent(),
          blazeFlagsEditor.createComponent(),
          exeFlagsEditor.createComponent(),
          keepInSyncCheckBox);
    }
  }
}
