package com.jetbrains.ther.run.run;

import com.intellij.execution.ExecutionResult;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.RunContentBuilder;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.jetbrains.ther.debugger.exception.TheRDebuggerException;
import com.jetbrains.ther.run.TheRXProcessHandler;
import com.jetbrains.ther.run.graphics.TheRGraphicsUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.concurrent.ExecutorService;

class TheRRunProcess {

  @NotNull
  private static final Logger LOGGER = Logger.getInstance(TheRRunProcess.class);

  @NotNull
  private final Project myProject;

  @NotNull
  private final ExecutionEnvironment myEnvironment;

  @NotNull
  private final ExecutionResult myExecutionResult;

  @NotNull
  private final List<String> myInitCommands;

  @NotNull
  private final ExecutorService myExecutor;

  public TheRRunProcess(@NotNull final Project project,
                        @NotNull final ExecutionEnvironment environment,
                        @NotNull final ExecutionResult executionResult,
                        @NotNull final List<String> initCommands,
                        @NotNull final ExecutorService executor) {
    myProject = project;
    myEnvironment = environment;
    myExecutionResult = executionResult;
    myInitCommands = initCommands;
    myExecutor = executor;
  }

  @NotNull
  public RunContentDescriptor getRunContentDescriptor() {
    TheRGraphicsUtils.getGraphicsState(myProject).reset();

    final TheRXProcessHandler processHandler = (TheRXProcessHandler)myExecutionResult.getProcessHandler();

    processHandler.addListener(new InitializationProcessListener(processHandler, myInitCommands, myExecutor));
    processHandler.addProcessListener(new TerminationProcessListener(myProject));

    return new RunContentBuilder(myExecutionResult, myEnvironment).showRunContent(myEnvironment.getContentToReuse());
  }

  private static class InitializationProcessListener implements TheRXProcessHandler.Listener {

    @NotNull
    private final TheRXProcessHandler myProcessHandler;

    @NotNull
    private final List<String> myInitCommands;

    @NotNull
    private final ExecutorService myExecutor;

    public InitializationProcessListener(@NotNull final TheRXProcessHandler processHandler,
                                         @NotNull final List<String> initCommands,
                                         @NotNull final ExecutorService executor) {
      myProcessHandler = processHandler;
      myInitCommands = initCommands;
      myExecutor = executor;
    }

    @Override
    public void onInitialized() {
      myExecutor.submit(
        new Runnable() {
          @Override
          public void run() {
            try {
              for (final String initCommand : myInitCommands) {
                myProcessHandler.execute(initCommand);
              }
            }
            catch (final TheRDebuggerException e) {
              LOGGER.error(e);
            }
            finally {
              myExecutor.shutdown();
            }
          }
        }
      );
    }
  }

  private static class TerminationProcessListener extends ProcessAdapter {

    @NotNull
    private final Project myProject;

    public TerminationProcessListener(@NotNull final Project project) {
      myProject = project;
    }

    @Override
    public void processTerminated(@Nullable final ProcessEvent event) {
      TheRGraphicsUtils.getGraphicsState(myProject).refresh(false);
    }
  }
}

@@ -486,39 +486,213 @@
 ger.
-exception.TheRDebuggerException
+TheRDebuggerStringUtils;%0Aimport com.jetbrains.ther.debugger.exception.TheRDebuggerException;%0Aimport com.jetbrains.ther.debugger.executor.TheRExecutorUtils;%0Aimport com.jetbrains.ther.run.TheRXOutputReceiver
 ;%0Aim
@@ -953,16 +953,36 @@
 rvice;%0A%0A
+// TODO %5Brun%5D%5Btest%5D%0A
 class Th
@@ -3255,130 +3255,372 @@
     
-try %7B%0A              for (final String initCommand : myInitCommands) %7B%0A                myProcessHandler.execute(initCommand
+final TheRXOutputReceiver outputReceiver = new TheRXOutputReceiver(myProcessHandler);%0A%0A            try %7B%0A              for (final String initCommand : myInitCommands) %7B%0A                TheRDebuggerStringUtils.appendResult(%0A                  TheRExecutorUtils.execute(myProcessHandler, initCommand, outputReceiver),%0A                  outputReceiver%0A                
 );%0A 

print output of running process