/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * 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.intellij.execution.actions;

import com.intellij.execution.Location;
import com.intellij.execution.PsiLocation;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.junit.RuntimeConfigurationProducer;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.Nullable;

import java.awt.*;
import java.util.List;

/**
 * Context for creating run configurations from a location in the source code.
 *
 * @see RunConfigurationProducer
 */
public class ConfigurationContext {
  private static final Logger LOG = Logger.getInstance("#com.intellij.execution.actions.ConfigurationContext");
  private final Location<PsiElement> myLocation;
  private RunnerAndConfigurationSettings myConfiguration;
  private Ref<RunnerAndConfigurationSettings> myExistingConfiguration;
  private final Module myModule;
  private final RunConfiguration myRuntimeConfiguration;
  private final Component myContextComponent;

  public static Key<ConfigurationContext> SHARED_CONTEXT = Key.create("SHARED_CONTEXT");
  private List<RuntimeConfigurationProducer> myPreferredProducers;
  private List<ConfigurationFromContext> myConfigurationsFromContext;

  public static ConfigurationContext getFromContext(DataContext dataContext) {
    final ConfigurationContext context = new ConfigurationContext(dataContext);
    final DataManager dataManager = DataManager.getInstance();
    ConfigurationContext sharedContext = dataManager.loadFromDataContext(dataContext, SHARED_CONTEXT);
    if (sharedContext == null ||
        sharedContext.getLocation() == null ||
        context.getLocation() == null ||
        !Comparing.equal(sharedContext.getLocation().getPsiElement(), context.getLocation().getPsiElement())) {
      sharedContext = context;
      dataManager.saveInDataContext(dataContext, SHARED_CONTEXT, sharedContext);
    }
    return sharedContext;
  }

  private ConfigurationContext(final DataContext dataContext) {
    myRuntimeConfiguration = RunConfiguration.DATA_KEY.getData(dataContext);
    myContextComponent = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
    myModule = LangDataKeys.MODULE.getData(dataContext);
    @SuppressWarnings({"unchecked"})
    final Location<PsiElement> location = (Location<PsiElement>)Location.DATA_KEY.getData(dataContext);
    if (location != null) {
      myLocation = location;
      return;
    }
    final Project project = CommonDataKeys.PROJECT.getData(dataContext);
    if (project == null) {
      myLocation = null;
      return;
    }
    final PsiElement element = getSelectedPsiElement(dataContext, project);
    if (element == null) {
      myLocation = null;
      return;
    }
    myLocation = new PsiLocation<PsiElement>(project, myModule, element);
  }

  /**
   * Returns the configuration created from this context.
   *
   * @return the configuration, or null if none of the producers were able to create a configuration from this context.
   */
  @Nullable
  public RunnerAndConfigurationSettings getConfiguration() {
    if (myConfiguration == null) createConfiguration();
    return myConfiguration;
  }

  private void createConfiguration() {
    LOG.assertTrue(myConfiguration == null);
    final Location location = getLocation();
    myConfiguration = location != null ?
        PreferredProducerFind.createConfiguration(location, this) :
        null;
  }

  public void setConfiguration(RunnerAndConfigurationSettings configuration) {
    myConfiguration = configuration;
  }

  @Deprecated
  @Nullable
  public RunnerAndConfigurationSettings updateConfiguration(final RuntimeConfigurationProducer producer) {
    myConfiguration = producer.getConfiguration();
    return myConfiguration;
  }

  /**
   * Returns the source code location for this context.
   *
   * @return the source code location, or null if no source code fragment is currently selected.
   */
  @Nullable
  public Location getLocation() {
    return myLocation;
  }

  /**
   * Returns the PSI element at caret for this context.
   *
   * @return the PSI element, or null if no source code fragment is currently selected.
   */
  @Nullable
  public PsiElement getPsiLocation() {
    return myLocation != null ? myLocation.getPsiElement() : null;
  }

  /**
   * Finds an existing run configuration matching the context.
   *
   * @return an existing configuration, or null if none was found.
   */
  @Nullable
  public RunnerAndConfigurationSettings findExisting() {
    if (myExistingConfiguration != null) return myExistingConfiguration.get();
    myExistingConfiguration = new Ref<RunnerAndConfigurationSettings>();
    if (myLocation == null) {
      return null;
    }

    final PsiElement psiElement = myLocation.getPsiElement();
    if (!psiElement.isValid()) {
      return null;
    }

    final List<RuntimeConfigurationProducer> producers = findPreferredProducers();
    if (myRuntimeConfiguration != null) {
      if (producers != null) {
        for (RuntimeConfigurationProducer producer : producers) {
          final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation, this);
          if (configuration != null && configuration.getConfiguration() == myRuntimeConfiguration) {
            myExistingConfiguration.set(configuration);
          }
        }
      }
      for (RunConfigurationProducer producer : Extensions.getExtensions(RunConfigurationProducer.EP_NAME)) {
        RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(this);
        if (configuration != null && configuration.getConfiguration() == myRuntimeConfiguration) {
          myExistingConfiguration.set(configuration);
        }
      }
    }
    if (producers != null) {
      for (RuntimeConfigurationProducer producer : producers) {
        final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation, this);
        if (configuration != null) {
          myExistingConfiguration.set(configuration);
        }
      }
    }
    for (RunConfigurationProducer producer : Extensions.getExtensions(RunConfigurationProducer.EP_NAME)) {
      RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(this);
      if (configuration != null) {
        myExistingConfiguration.set(configuration);
      }
    }
    return myExistingConfiguration.get();
  }

  @Nullable
  private static PsiElement getSelectedPsiElement(final DataContext dataContext, final Project project) {
    PsiElement element = null;
    final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
    if (editor != null){
      final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
      if (psiFile != null) {
        final int offset = editor.getCaretModel().getOffset();
        element = psiFile.findElementAt(offset);
        if (element == null && offset > 0 && offset == psiFile.getTextLength()) {
          element = psiFile.findElementAt(offset-1);
        }
      }
    }
    if (element == null) {
      final PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
      element = elements != null && elements.length > 0 ? elements[0] : null;
    }
    if (element == null) {
      final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
      if (files != null && files.length > 0) {
        element = PsiManager.getInstance(project).findFile(files[0]);
      }
    }
    return element;
  }

  public RunManager getRunManager() {
    return RunManager.getInstance(getProject());
  }

  public Project getProject() {
    return myLocation.getProject();
  }

  public Module getModule() {
    return myModule;
  }

  public DataContext getDataContext() {
    return DataManager.getInstance().getDataContext(myContextComponent);
  }

  /**
   * Returns original {@link RunConfiguration} from this context.
   * For example, it could be some test framework runtime configuration that had been launched
   * and that had brought a result test tree on which a right-click action was performed.
   *
   * @param type {@link ConfigurationType} instance to filter original runtime configuration by its type
   * @return {@link RunConfiguration} instance, it could be null
   */
  @Nullable
  public RunConfiguration getOriginalConfiguration(@Nullable ConfigurationType type) {
    if (type == null) {
      return myRuntimeConfiguration;
    }
    if (myRuntimeConfiguration != null
        && ConfigurationTypeUtil.equals(myRuntimeConfiguration.getType(), type)) {
      return myRuntimeConfiguration;
    }
    return null;
  }

  @Deprecated
  @Nullable
  public List<RuntimeConfigurationProducer> findPreferredProducers() {
    if (myPreferredProducers == null) {
      myPreferredProducers = PreferredProducerFind.findPreferredProducers(myLocation, this, true);
    }
    return myPreferredProducers;
  }

  public List<ConfigurationFromContext> getConfigurationsFromContext() {
    if (myConfigurationsFromContext == null) {
      myConfigurationsFromContext = PreferredProducerFind.getConfigurationsFromContext(myLocation, this, true);
    }
    return myConfigurationsFromContext;
  }
}
