package fr.adrienbrault.idea.symfony2plugin.installer;

import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.*;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

/**
 * @author Daniel Espendiller <daniel@espendiller.net>
 */
abstract public class SymfonyInstallerCommandExecutor {

    private static final long CHECKING_TIMEOUT_IN_MILLISECONDS = 1000L;
    private final Project myProject;
    private final VirtualFile baseDir;
    private final String[] command;

    public SymfonyInstallerCommandExecutor(@NotNull Project project, @NotNull VirtualFile baseDir, @NotNull String[] command) {
        this.myProject = project;
        this.baseDir = baseDir;
        this.command = command;
    }

    public void execute()  {
        Task task = new Task.Modal(this.myProject, getProgressTitle(), true) {
            public void run(@NotNull final ProgressIndicator indicator) {
                indicator.setIndeterminate(true);

                String[] myCommand = SymfonyInstallerCommandExecutor.this.command;

                StringBuilder sb = new StringBuilder();
                sb.append("Running: ");
                for (String aCommandToRun : Arrays.copyOfRange(myCommand, 1, myCommand.length)) {
                    if (aCommandToRun.length() > 35) {
                        aCommandToRun = "..." + aCommandToRun.substring(aCommandToRun.length() - 35);
                    }
                    sb.append(" ").append(aCommandToRun);
                }
                indicator.setText(sb.toString());

                boolean cancelledByUser = false;
                final StringBuilder outputBuilder = new StringBuilder();
                try {
                    OSProcessHandler processHandler = ScriptRunnerUtil.execute(myCommand[0], SymfonyInstallerCommandExecutor.this.baseDir.getPath(), null, Arrays.copyOfRange(myCommand, 1, myCommand.length));

                    processHandler.addProcessListener(new ProcessAdapter() {
                        @Override
                        public void onTextAvailable(ProcessEvent event, com.intellij.openapi.util.Key outputType) {
                            String text = event.getText();
                            outputBuilder.append(text);

                            text = SymfonyInstallerUtil.formatConsoleTextIndicatorOutput(text);
                            if(StringUtils.isNotBlank(text)) {
                                indicator.setText2(text);
                            }

                        }
                    });

                    processHandler.startNotify();
                    for (;;){
                        boolean finished = processHandler.waitFor(CHECKING_TIMEOUT_IN_MILLISECONDS);
                        if (finished) {
                            break;
                        }
                        if (indicator.isCanceled()) {
                            cancelledByUser = true;
                            OSProcessManager.getInstance().killProcessTree(processHandler.getProcess());
                            break;
                        }
                    }

                }

                catch (ExecutionException e) {
                    onError(e.getMessage());
                    return;
                }

                if(cancelledByUser) {
                    onError("Checkout canceled");
                    return;
                }

                String output = outputBuilder.toString();
                if (StringUtils.isBlank(output) || !SymfonyInstallerUtil.isSuccessfullyInstalled(output)) {

                    String message = SymfonyInstallerUtil.formatExceptionMessage(output);
                    if(message == null) {
                        message = "The unexpected happens...";
                    }

                    onError(message);
                    return;
                }

                indicator.setText2("Preparing Project Structure...");
                try {
                    File fromDir = new File(baseDir.getPath() + "/" + SymfonyInstallerUtil.PROJECT_SUB_FOLDER);
                    FileUtil.copyDirContent(fromDir, new File(baseDir.getPath()));
                    FileUtil.delete(fromDir);
                } catch (IOException e) {
                    onError(e.getMessage());
                    return;
                }

                onFinish(SymfonyInstallerUtil.extractSuccessMessage(output));
            }
        };

        ProgressManager.getInstance().run(task);
    }

    abstract protected void onFinish(@Nullable String successMessage);
    abstract protected void onError(@NotNull String message);
    protected abstract String getProgressTitle();

}
@@ -3639,32 +3639,69 @@
                 
+SymfonyInstallerCommandExecutor.this.
 onError(e.getMes
@@ -3806,32 +3806,69 @@
                 
+SymfonyInstallerCommandExecutor.this.
 onError(%22Checkou
@@ -4325,32 +4325,69 @@
                 
+SymfonyInstallerCommandExecutor.this.
 onError(message)
@@ -4830,16 +4830,53 @@
         
+SymfonyInstallerCommandExecutor.this.
 onError(
@@ -4955,16 +4955,53 @@
         
+SymfonyInstallerCommandExecutor.this.
 onFinish

fix method signature collision in Symfony installer executor