/*
 * 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.base.run;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.primitives.Kind;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.TargetExpression;
import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationHandler;
import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationHandlerProvider;
import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationRunner;
import com.google.idea.blaze.base.run.state.RunConfigurationState;
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.ui.UiUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.RunnerIconProvider;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.LocatableConfigurationBase;
import com.intellij.execution.configurations.ModuleRunProfile;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunConfigurationWithSuppressedDefaultDebugAction;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.ui.TextFieldWithAutoCompletion;
import com.intellij.ui.TextFieldWithAutoCompletion.StringsCompletionProvider;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ui.UIUtil;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JComponent;
import org.jdom.Attribute;
import org.jdom.Element;

/** A run configuration which executes Blaze commands. */
public class BlazeCommandRunConfiguration extends LocatableConfigurationBase
    implements BlazeRunConfiguration,
        RunnerIconProvider,
        ModuleRunProfile,
        RunConfigurationWithSuppressedDefaultDebugAction {

  private static final Logger logger = Logger.getInstance(BlazeCommandRunConfiguration.class);

  private static final String HANDLER_ATTR = "handler-id";
  private static final String TARGET_TAG = "blaze-target";
  private static final String KIND_ATTR = "kind";
  private static final String KEEP_IN_SYNC_TAG = "keep-in-sync";

  /**
   * This tag is actually written by {@link com.intellij.execution.impl.RunManagerImpl}; it
   * represents the before-run tasks of the configuration. We need to know about it to avoid writing
   * it ourselves.
   */
  private static final String METHOD_TAG = "method";

  /** The last serialized state of the configuration. */
  private Element elementState = new Element("dummy");

  @Nullable private TargetExpression target;
  // Null if the target is null, not a Label, or not a known rule.
  @Nullable private Kind targetKind;

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

  private BlazeCommandRunConfigurationHandlerProvider handlerProvider;
  private BlazeCommandRunConfigurationHandler handler;

  public BlazeCommandRunConfiguration(Project project, ConfigurationFactory factory, String name) {
    super(project, factory, name);
    // start with whatever fallback is present
    handlerProvider = BlazeCommandRunConfigurationHandlerProvider.findHandlerProvider(null);
    handler = handlerProvider.createHandler(this);
    try {
      handler.getState().readExternal(elementState);
    } catch (InvalidDataException e) {
      logger.error(e);
    }
  }

  /** @return The configuration's {@link BlazeCommandRunConfigurationHandler}. */
  public BlazeCommandRunConfigurationHandler getHandler() {
    return handler;
  }

  /**
   * Gets the configuration's handler's {@link RunConfigurationState} if it is an instance of the
   * given class; otherwise returns null.
   */
  @Nullable
  public <T extends RunConfigurationState> T getHandlerStateIfType(Class<T> type) {
    RunConfigurationState handlerState = handler.getState();
    if (type.isInstance(handlerState)) {
      return type.cast(handlerState);
    } else {
      return null;
    }
  }

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

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

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

  public void setTarget(@Nullable TargetExpression target) {
    this.target = target;
    updateHandler();
  }

  private void updateHandler() {
    targetKind = getKindForTarget();

    BlazeCommandRunConfigurationHandlerProvider handlerProvider =
        BlazeCommandRunConfigurationHandlerProvider.findHandlerProvider(targetKind);
    updateHandlerIfDifferentProvider(handlerProvider);
  }

  private void updateHandlerIfDifferentProvider(
      BlazeCommandRunConfigurationHandlerProvider newProvider) {
    if (handlerProvider == newProvider) {
      return;
    }
    try {
      handler.getState().writeExternal(elementState);
    } catch (WriteExternalException e) {
      logger.error(e);
    }
    handlerProvider = newProvider;
    handler = newProvider.createHandler(this);
    try {
      handler.getState().readExternal(elementState);
    } catch (InvalidDataException e) {
      logger.error(e);
    }
  }

  /**
   * Returns the {@link Kind} of the single blaze target corresponding to the configuration's target
   * expression, if it can be determined. Returns null if the target expression points to multiple
   * blaze targets.
   */
  @Nullable
  public Kind getKindForTarget() {
    if (target instanceof Label) {
      TargetIdeInfo target =
          TargetFinder.getInstance().targetForLabel(getProject(), (Label) this.target);
      return target != null ? target.kind : null;
    }
    return null;
  }

  /**
   * @return The {@link Kind} name, if the target is a known rule. Otherwise, "target pattern" if it
   *     is a general {@link TargetExpression}, "unknown rule" if it is a {@link Label} without a
   *     known rule, and "unknown target" if there is no target.
   */
  public String getTargetKindName() {
    Kind kind = getKindForTarget();
    if (kind != null) {
      return kind.toString();
    } else if (target instanceof Label) {
      return "unknown rule";
    } else if (target != null) {
      return "target pattern";
    } else {
      return "unknown target";
    }
  }

  @Override
  public void checkConfiguration() throws RuntimeConfigurationException {
    // Our handler check is not valid when we don't have BlazeProjectData.
    if (BlazeProjectDataManager.getInstance(getProject()).getBlazeProjectData() == null) {
      throw new RuntimeConfigurationError(
          "Configuration cannot be run until project has been synced.");
    }
    if (target == null) {
      throw new RuntimeConfigurationError(
          String.format(
              "You must specify a %s target expression.", Blaze.buildSystemName(getProject())));
    }
    if (!target.toString().startsWith("//")) {
      throw new RuntimeConfigurationError(
          "You must specify the full target expression, starting with //");
    }
    handler.checkConfiguration();
  }

  @Override
  public void readExternal(Element element) throws InvalidDataException {
    super.readExternal(element);
    element = element.clone();

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

    // 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 = TargetExpression.fromString(targetElement.getTextTrim());
      targetKind = Kind.fromString(targetElement.getAttributeValue(KIND_ATTR));
    } else {
      // Legacy: Added in 1.9 to support reading target as an attribute so
      // BlazeAndroid(Binary/Test)RunConfiguration elements can be read.
      // TODO remove in 2.1 once BlazeAndroidBinaryRunConfigurationType and
      // BlazeAndroidTestRunConfigurationType have been removed.
      String targetString = element.getAttributeValue(TARGET_TAG);
      target = targetString != null ? TargetExpression.fromString(targetString) : null;
    }
    // Because BlazeProjectData is not available when configurations are loading,
    // we can't call setTarget and have it find the appropriate handler provider.
    // So instead, we use the stored provider ID.
    String providerId = element.getAttributeValue(HANDLER_ATTR);
    BlazeCommandRunConfigurationHandlerProvider handlerProvider =
        BlazeCommandRunConfigurationHandlerProvider.getHandlerProvider(providerId);
    if (handlerProvider != null) {
      updateHandlerIfDifferentProvider(handlerProvider);
    }

    element.removeAttribute(KIND_ATTR);
    element.removeAttribute(HANDLER_ATTR);
    element.removeChildren(TARGET_TAG);
    element.removeAttribute(KEEP_IN_SYNC_TAG);
    // remove legacy attribute, if present
    element.removeAttribute(TARGET_TAG);

    this.elementState = element;
    handler.getState().readExternal(elementState);
  }

  @Override
  @SuppressWarnings("ThrowsUncheckedException")
  public void writeExternal(Element element) throws WriteExternalException {
    super.writeExternal(element);
    if (target != null) {
      Element targetElement = new Element(TARGET_TAG);
      targetElement.setText(target.toString());
      if (targetKind != null) {
        targetElement.setAttribute(KIND_ATTR, targetKind.toString());
      }
      element.addContent(targetElement);
    }
    if (keepInSync != null) {
      element.setAttribute(KEEP_IN_SYNC_TAG, Boolean.toString(keepInSync));
    }
    element.setAttribute(HANDLER_ATTR, handlerProvider.getId());

    handler.getState().writeExternal(elementState);

    // copy our internal state to the provided Element, skipping items already present
    Set<String> baseAttributes =
        element.getAttributes().stream().map(Attribute::getName).collect(Collectors.toSet());
    for (Attribute attribute : elementState.getAttributes()) {
      if (!baseAttributes.contains(attribute.getName())) {
        element.setAttribute(attribute.clone());
      }
    }
    Set<String> baseChildren =
        element.getChildren().stream().map(Element::getName).collect(Collectors.toSet());
    // The method tag is written by RunManagerImpl *after* this writeExternal call,
    // so it isn't already present.
    // We still have to avoid writing it ourselves, or we wind up duplicating it.
    baseChildren.add(METHOD_TAG);
    for (Element child : elementState.getChildren()) {
      if (!baseChildren.contains(child.getName())) {
        element.addContent(child.clone());
      }
    }
  }

  @Override
  public BlazeCommandRunConfiguration clone() {
    final BlazeCommandRunConfiguration configuration = (BlazeCommandRunConfiguration) super.clone();
    configuration.elementState = elementState.clone();
    configuration.target = target;
    configuration.targetKind = targetKind;
    configuration.keepInSync = keepInSync;
    configuration.handlerProvider = handlerProvider;
    configuration.handler = handlerProvider.createHandler(this);
    try {
      configuration.handler.getState().readExternal(configuration.elementState);
    } catch (InvalidDataException e) {
      logger.error(e);
    }

    return configuration;
  }

  @Override
  @Nullable
  public RunProfileState getState(Executor executor, ExecutionEnvironment environment)
      throws ExecutionException {
    if (target != null) {
      // We need to update the handler manually because it might otherwise be out of date (e.g.
      // because the target map has changed since the last update).
      updateHandler();
    }
    BlazeCommandRunConfigurationRunner runner = handler.createRunner(executor, environment);
    if (runner != null) {
      environment.putCopyableUserData(BlazeCommandRunConfigurationRunner.RUNNER_KEY, runner);
      return runner.getRunProfileState(executor, environment);
    }
    return null;
  }

  @Override
  @Nullable
  public String suggestedName() {
    return handler.suggestedName(this);
  }

  @Override
  @Nullable
  public Icon getExecutorIcon(RunConfiguration configuration, Executor executor) {
    return handler.getExecutorIcon(configuration, executor);
  }

  @Override
  public SettingsEditor<? extends BlazeCommandRunConfiguration> getConfigurationEditor() {
    return new BlazeCommandRunConfigurationSettingsEditor(this);
  }

  @Override
  public Module[] getModules() {
    return new Module[0];
  }

  static class BlazeCommandRunConfigurationSettingsEditor
      extends SettingsEditor<BlazeCommandRunConfiguration> {

    private BlazeCommandRunConfigurationHandlerProvider handlerProvider;
    private BlazeCommandRunConfigurationHandler handler;
    private RunConfigurationStateEditor handlerStateEditor;
    private JComponent handlerStateComponent;
    private Element elementState;

    private final Box editorWithoutSyncCheckBox;
    private final Box editor;
    private final JBCheckBox keepInSyncCheckBox;
    private final JBLabel targetExpressionLabel;
    private final TextFieldWithAutoCompletion<String> targetField;

    BlazeCommandRunConfigurationSettingsEditor(BlazeCommandRunConfiguration config) {
      Project project = config.getProject();
      targetField =
          new TextFieldWithAutoCompletion<>(
              project, new TargetCompletionProvider(project), true, null);
      elementState = config.elementState.clone();
      targetExpressionLabel = new JBLabel(UIUtil.ComponentStyle.LARGE);
      keepInSyncCheckBox = new JBCheckBox("Keep in sync with source XML");
      editorWithoutSyncCheckBox = UiUtil.createBox(targetExpressionLabel, targetField);
      editor = UiUtil.createBox(editorWithoutSyncCheckBox, keepInSyncCheckBox);
      updateEditor(config);
      updateHandlerEditor(config);
      keepInSyncCheckBox.addItemListener(e -> updateEnabledStatus());
    }

    private void updateEditor(BlazeCommandRunConfiguration config) {
      targetExpressionLabel.setText(
          String.format(
              "Target expression (%s handled by %s):",
              config.getTargetKindName(), config.handler.getHandlerName()));
      keepInSyncCheckBox.setVisible(config.keepInSync != null);
      if (config.keepInSync != null) {
        keepInSyncCheckBox.setSelected(config.keepInSync);
      }
      updateEnabledStatus();
    }

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

    private void setEnabled(boolean enabled) {
      if (handlerStateEditor != null) {
        handlerStateEditor.setComponentEnabled(enabled);
      }
      targetField.setEnabled(enabled);
    }

    private void updateHandlerEditor(BlazeCommandRunConfiguration config) {
      handlerProvider = config.handlerProvider;
      handler = handlerProvider.createHandler(config);
      try {
        handler.getState().readExternal(config.elementState);
      } catch (InvalidDataException e) {
        logger.error(e);
      }
      handlerStateEditor = handler.getState().getEditor(config.getProject());

      if (handlerStateComponent != null) {
        editorWithoutSyncCheckBox.remove(handlerStateComponent);
      }
      handlerStateComponent = handlerStateEditor.createComponent();
      editorWithoutSyncCheckBox.add(handlerStateComponent);
    }

    @Override
    protected JComponent createEditor() {
      return editor;
    }

    @Override
    protected void resetEditorFrom(BlazeCommandRunConfiguration config) {
      elementState = config.elementState.clone();
      updateEditor(config);
      if (config.handlerProvider != handlerProvider) {
        updateHandlerEditor(config);
      }
      targetField.setText(config.target == null ? null : config.target.toString());
      handlerStateEditor.resetEditorFrom(config.handler.getState());
    }

    @Override
    protected void applyEditorTo(BlazeCommandRunConfiguration config) {
      // update the editor's elementState
      handlerStateEditor.applyEditorTo(handler.getState());
      try {
        handler.getState().writeExternal(elementState);
      } catch (WriteExternalException e) {
        logger.error(e);
      }
      config.keepInSync = keepInSyncCheckBox.isVisible() ? keepInSyncCheckBox.isSelected() : null;

      // now set the config's state, based on the editor's (possibly out of date) handler
      config.updateHandlerIfDifferentProvider(handlerProvider);
      config.elementState = elementState.clone();
      try {
        config.handler.getState().readExternal(config.elementState);
      } catch (InvalidDataException e) {
        logger.error(e);
      }

      // finally, update the handler
      String targetString = targetField.getText();
      config.setTarget(
          Strings.isNullOrEmpty(targetString) ? null : TargetExpression.fromString(targetString));
      updateEditor(config);
      if (config.handlerProvider != handlerProvider) {
        updateHandlerEditor(config);
        handlerStateEditor.resetEditorFrom(config.handler.getState());
      } else {
        handlerStateEditor.applyEditorTo(config.handler.getState());
      }
    }
  }

  private static class TargetCompletionProvider extends StringsCompletionProvider {
    TargetCompletionProvider(Project project) {
      super(getTargets(project), null);
    }

    private static Collection<String> getTargets(Project project) {
      List<String> result = Lists.newArrayList();
      BlazeProjectData projectData =
          BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
      if (projectData != null) {
        for (TargetIdeInfo target : projectData.targetMap.targets()) {
          if (target.isPlainTarget()) {
            result.add(target.key.label.toString());
          }
        }
      }
      return result;
    }
  }
}
