package com.bluepapa32.gradle.plugins.watch;

import java.io.PrintStream;
import java.util.List;

import org.gradle.api.Project;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.plugins.announce.AnnouncePluginExtension;
import org.gradle.api.plugins.announce.BuildAnnouncementsPlugin;
import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.BuildException;
import org.gradle.tooling.GradleConnectionException;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProgressEvent;
import org.gradle.tooling.ProgressListener;
import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.ResultHandler;

import static org.gradle.api.logging.LogLevel.INFO;

public class WatchTargetTaskRunner implements AutoCloseable {

    private ProjectConnection connection;

    private AnnouncePluginExtension announce;

    public WatchTargetTaskRunner(Project project) {

        if (!project.getPlugins().hasPlugin(BuildAnnouncementsPlugin.class)) {
            announce = project.getExtensions().findByType(AnnouncePluginExtension.class);
        }

        final PrintStream out = System.out;

        LogLevel logLevel = project.getGradle().getStartParameter().getLogLevel();
        if (INFO.compareTo(logLevel) < 0) {
            System.setOut(new DevNullPrintStream());
        }

        out.print("Starting");
        out.flush();

        connection = GradleConnector.newConnector()
                .useInstallation(project.getGradle().getGradleHomeDir())
                .forProjectDirectory(project.getProjectDir())
                .connect();

        connection
            .newBuild()
            .withArguments("-q")
            .addProgressListener(new ProgressListener() {
                public void statusChanged(ProgressEvent event) {
                    out.print("..");
                    out.flush();
                }
            })
            .run(new ResultHandler<Void>() {
                public void onComplete(Void result) {
                    System.setOut(out);
                    out.println(" \033[32mOK\033[39m");
                }
                public void onFailure(GradleConnectionException failure) {
                }
            });
    }

    public void run(List<WatchTarget> targets) {

        if (targets == null || targets.isEmpty()) {
            return;
        }

        BuildLauncher launcher = connection.newBuild();

        for (WatchTarget target : targets) {
            launcher.forTasks(target.getTasks().toArray(new String[0]));
        }

        final int[] taskNum = new int[1];

        launcher.addProgressListener(new ProgressListener() {
            public void statusChanged(ProgressEvent event) {
                if ("Execute tasks".equals(event.getDescription())) {
                    taskNum[0]++;
                }
            }
        });

        long timestamp = System.currentTimeMillis();

        try {

            launcher.run();
            if (announce != null) {
                announce.getLocal().send("Build success", (taskNum[0] - 1) + " tasks executed");
            }

        } catch (BuildException e) {
            if (announce != null) {
                announce.getLocal().send("Build failure", e.getCause().getMessage());
            }
        }

        for (WatchTarget target : targets) {
            target.setExecutedAt(timestamp);
        }
    }

    public void close() {
        connection.close();
    }
}

@@ -166,137 +166,8 @@
 el;%0A
-import org.gradle.api.plugins.announce.AnnouncePluginExtension;%0Aimport org.gradle.api.plugins.announce.BuildAnnouncementsPlugin;%0A
 impo
@@ -681,281 +681,54 @@
    p
-rivate AnnouncePluginExtension announce;%0A%0A    public WatchTargetTaskRunner(Project project) %7B%0A%0A        if (!project.getPlugins().hasPlugin(BuildAnnouncementsPlugin.class)) %7B%0A            announce = project.getExtensions().findByType(AnnouncePluginExtension.class);%0A        %7D
+ublic WatchTargetTaskRunner(Project project) %7B
 %0A%0A  
@@ -2596,328 +2596,70 @@
 ();%0A
-            if (announce != null) %7B%0A                announce.getLocal().send(%22Build success%22, (taskNum%5B0%5D - 1) + %22 tasks executed%22);%0A            %7D%0A%0A        %7D catch (BuildException e) %7B%0A            if (announce != null) %7B%0A                announce.getLocal().send(%22Build failure%22, e.getCause().getMessage());%0A            %7D
+%0A        %7D catch (BuildException e) %7B%0A            // ignore...
 %0A   

Build Announcement Plugin 連携の仕様追加を除外