/*
 * Copyright 2017 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.producer;

import com.google.idea.blaze.base.BlazeIntegrationTestCase;
import com.google.idea.blaze.base.EditorTestHelper;
import com.google.idea.blaze.base.command.BlazeCommandName;
import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
import com.google.idea.blaze.base.model.MockBlazeProjectDataBuilder;
import com.google.idea.blaze.base.model.MockBlazeProjectDataManager;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
import com.google.idea.blaze.base.run.state.BlazeCommandRunConfigurationCommonState;
import com.google.idea.blaze.base.sync.SyncCache;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
import com.intellij.execution.Location;
import com.intellij.execution.PsiLocation;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.ide.DataManager;
import com.intellij.idea.CommandLineApplication.MyDataManagerImpl;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.MapDataContext;
import javax.annotation.Nullable;
import org.junit.After;
import org.junit.Before;

/** Run configuration producer integration test base */
public class BlazeRunConfigurationProducerTestCase extends BlazeIntegrationTestCase {

  protected EditorTestHelper editorTest;

  @Before
  public final void doSetup() {
    BlazeProjectDataManager mockProjectDataManager =
        new MockBlazeProjectDataManager(MockBlazeProjectDataBuilder.builder(workspaceRoot).build());
    registerProjectService(BlazeProjectDataManager.class, mockProjectDataManager);
    editorTest = new EditorTestHelper(getProject(), testFixture);

    // IntelliJ replaces the normal DataManager with a mock version in headless environments.
    // We rely on a functional DataManager in run configuration tests to recognize when multiple
    // psi elements are selected.
    DataManager dataManager =
        new MyDataManagerImpl() {
          DataContext dataContext;

          @Override
          public <T> void saveInDataContext(
              DataContext dataContext, Key<T> dataKey, @Nullable T data) {
            this.dataContext = dataContext;
            super.saveInDataContext(dataContext, dataKey, data);
          }

          @Override
          public DataContext getDataContext() {
            return dataContext != null ? dataContext : super.getDataContext();
          }
        };
    registerApplicationComponent(DataManager.class, dataManager);
  }

  @After
  public final void doTearDown() {
    SyncCache.getInstance(getProject()).clear();
  }

  protected PsiFile createAndIndexFile(WorkspacePath path, String... contents) {
    PsiFile file = workspace.createPsiFile(path, contents);
    editorTest.openFileInEditor(file); // open file to trigger update of indices
    return file;
  }

  @Nullable
  protected static String getTestFilterContents(BlazeCommandRunConfiguration config) {
    BlazeCommandRunConfigurationCommonState handlerState =
        config.getHandlerStateIfType(BlazeCommandRunConfigurationCommonState.class);
    return handlerState != null ? handlerState.getTestFilterFlag() : null;
  }

  @Nullable
  protected static BlazeCommandName getCommandType(BlazeCommandRunConfiguration config) {
    BlazeCommandRunConfigurationCommonState handlerState =
        config.getHandlerStateIfType(BlazeCommandRunConfigurationCommonState.class);
    return handlerState != null ? handlerState.getCommand() : null;
  }

  protected ConfigurationContext createContextFromPsi(PsiElement element) {
    final MapDataContext dataContext = new MapDataContext();
    dataContext.put(CommonDataKeys.PROJECT, getProject());
    dataContext.put(LangDataKeys.MODULE, ModuleUtil.findModuleForPsiElement(element));
    dataContext.put(Location.DATA_KEY, PsiLocation.fromPsiElement(element));
    return ConfigurationContext.getFromContext(dataContext);
  }

  protected ConfigurationContext createContextFromMultipleElements(PsiElement[] elements) {
    final MapDataContext dataContext = new MapDataContext();
    dataContext.put(CommonDataKeys.PROJECT, getProject());
    dataContext.put(LangDataKeys.MODULE, ModuleUtil.findModuleForPsiElement(elements[0]));
    dataContext.put(Location.DATA_KEY, PsiLocation.fromPsiElement(elements[0]));
    dataContext.put(LangDataKeys.PSI_ELEMENT_ARRAY, elements);
    return ConfigurationContext.getFromContext(dataContext);
  }

  @Nullable
  protected RunConfiguration createConfigurationFromLocation(PsiFile psiFile) {
    MapDataContext dataContext = new MapDataContext();
    dataContext.put(CommonDataKeys.PROJECT, getProject());
    dataContext.put(LangDataKeys.MODULE, ModuleUtil.findModuleForPsiElement(psiFile));
    dataContext.put(Location.DATA_KEY, PsiLocation.fromPsiElement(psiFile));
    RunnerAndConfigurationSettings settings =
        ConfigurationContext.getFromContext(dataContext).getConfiguration();
    return settings != null ? settings.getConfiguration() : null;
  }

  protected static ArtifactLocation sourceRoot(String relativePath) {
    return ArtifactLocation.builder().setRelativePath(relativePath).setIsSource(true).build();
  }
}
