package jetbrains.mps.execution.configurations.implementation.plugin.plugin;

/*Generated by MPS */

import jetbrains.mps.debug.api.run.DebuggerRunProfileState;
import com.intellij.execution.configurations.RunProfileState;
import org.jetbrains.annotations.NotNull;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
import com.intellij.execution.configurations.RunnerSettings;
import org.jetbrains.annotations.Nullable;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ExecutionException;
import com.intellij.openapi.project.Project;
import jetbrains.mps.baseLanguage.unitTest.execution.settings.JUnitSettings_Configuration;
import com.intellij.execution.executors.DefaultDebugExecutor;
import jetbrains.mps.project.MPSProject;
import jetbrains.mps.ide.project.ProjectHelper;
import java.util.List;
import jetbrains.mps.baseLanguage.unitTest.execution.client.ITestNodeWrapper;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.baseLanguage.unitTest.execution.client.TestRunState;
import com.intellij.execution.process.ProcessHandler;
import jetbrains.mps.baseLanguage.unitTest.execution.tool.UnitTestViewComponent;
import com.intellij.execution.process.ProcessListener;
import jetbrains.mps.baseLanguage.unitTest.execution.client.UnitTestProcessListener;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import jetbrains.mps.execution.api.configurations.DefaultExecutionResult;
import jetbrains.mps.execution.api.configurations.DefaultExecutionConsole;
import jetbrains.mps.debug.api.run.IDebuggerConfiguration;
import jetbrains.mps.debug.api.IDebuggerSettings;
import jetbrains.mps.debugger.java.api.settings.LocalConnectionSettings;
import jetbrains.mps.debug.api.IDebugger;
import jetbrains.mps.debug.api.Debuggers;
import com.intellij.execution.executors.DefaultRunExecutor;

public class JUnitTests_Configuration_RunProfileState extends DebuggerRunProfileState implements RunProfileState {
  @NotNull
  private final JUnitTests_Configuration myRunConfiguration;
  @NotNull
  private final ExecutionEnvironment myEnvironment;

  public JUnitTests_Configuration_RunProfileState(@NotNull JUnitTests_Configuration configuration, @NotNull Executor executor, @NotNull ExecutionEnvironment environment) {
    myRunConfiguration = configuration;
    myEnvironment = environment;
  }

  public ConfigurationPerRunnerSettings getConfigurationSettings() {
    return null;
  }

  public RunnerSettings getRunnerSettings() {
    return null;
  }

  @Nullable
  public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
    Project project = myEnvironment.getProject();
    JUnitSettings_Configuration junitParams = myRunConfiguration.getJUnitSettings();
    boolean debugExecutor = executor.getId().equals(DefaultDebugExecutor.EXECUTOR_ID);
    junitParams.setDebug(debugExecutor);
    MPSProject mpsProject = ProjectHelper.fromIdeaProject(project);
    List<ITestNodeWrapper> testNodes = junitParams.getTests(mpsProject);
    if (testNodes == null || ListSequence.fromList(testNodes).isEmpty()) {
      throw new ExecutionException("Could not find tests to run. Please check the run configuration for errors.");
    }
    TestRunState runState = new TestRunState(testNodes);
    JUnitProcessStarter processExecutor;
    if (junitParams.canExecuteInProcess()) {
      processExecutor = new JUnitInProcessRunStarter(mpsProject, myRunConfiguration, testNodes);
    } else {
      JUnitTests_Configuration configuration = myRunConfiguration;
      processExecutor = new JUnitOutOfProcessStarter(mpsProject, testNodes, configuration, executor.getId(), myDebuggerSettings);
    }
    ProcessHandler process = processExecutor.execute();
    final UnitTestViewComponent testViewComponent = myRunConfiguration.createTestViewComponent(runState, process, executor, myRunConfiguration);
    ProcessListener listener = new UnitTestProcessListener(runState);
    _FunctionTypes._void_P0_E0 disposeHandler = () -> testViewComponent.dispose();
    {
      ProcessHandler _processHandler = process;
      _processHandler.addProcessListener(listener);
      return new DefaultExecutionResult(_processHandler, new DefaultExecutionConsole(testViewComponent, disposeHandler));
    }
  }

  @NotNull
  public IDebuggerConfiguration getDebuggerConfiguration() {
    return new IDebuggerConfiguration() {
      @Nullable
      public IDebuggerSettings createDebuggerSettings() {
        return new LocalConnectionSettings(true);
      }
      public IDebugger getDebugger() {
        return Debuggers.getInstance().getDebuggerByName("Java");
      }
    };
  }

  public static boolean canExecute(String executorId) {
    if (DefaultRunExecutor.EXECUTOR_ID.equals(executorId)) {
      return true;
    }
    if (DefaultDebugExecutor.EXECUTOR_ID.equals(executorId)) {
      return true;
    }
    return false;
  }
}
