package org.utplsql.cli;

import org.utplsql.api.compatibility.CompatibilityProxy;
import org.utplsql.api.reporter.CoreReporters;
import org.utplsql.api.reporter.Reporter;
import org.utplsql.api.reporter.ReporterFactory;
import org.utplsql.cli.reporters.ReporterOptionsAware;

import javax.sql.DataSource;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;

class ReporterManager {

    private List<ReporterOptions> reporterOptionsList;
    private List<Throwable> reporterGatherErrors;
    private ExecutorService executorService;

    ReporterManager(List<String> reporterParams ) {
        parseReporterOptionsList(reporterParams);
        initReporterOptionsList();
    }

    ReporterManager( ReporterOptions[] reporterOptions ) {
        this.reporterOptionsList = Arrays.asList(reporterOptions);
        initReporterOptionsList();
    }

    private void parseReporterOptionsList( List<String> reporterParams ) {
        reporterOptionsList = new ArrayList<>();
        ReporterOptions reporterOptions = null;

        for (String p : reporterParams) {
            if (reporterOptions == null || !p.startsWith("-")) {
                reporterOptions = new ReporterOptions(p);
                reporterOptionsList.add(reporterOptions);
            }
            else
            if (p.startsWith("-o=")) {
                reporterOptions.setOutputFileName(p.substring(3));
            }
            else
            if (p.equals("-s")) {
                reporterOptions.forceOutputToScreen(true);
            }
        }
    }

    private void initReporterOptionsList( ) {

        // If no reporter parameters were passed, use default reporter.
        if (reporterOptionsList.isEmpty()) {
            reporterOptionsList = new ArrayList<>();
            reporterOptionsList.add(getDefaultReporterOption());
        }
    }

    private ReporterOptions getDefaultReporterOption() {
        return new ReporterOptions(CoreReporters.UT_DOCUMENTATION_REPORTER.name());
    }

    private void abortGathering(Throwable e) {
        addGatherError(e);
        executorService.shutdownNow();
    }

    private void addGatherError( Throwable e ) {
        if ( reporterGatherErrors == null ) {
            reporterGatherErrors = new ArrayList<>();
        }
        reporterGatherErrors.add(e);
    }

    boolean haveGatherErrorsOccured() {
        return reporterGatherErrors != null && !reporterGatherErrors.isEmpty();
    }

    List<Throwable> getGatherErrors() {
        return reporterGatherErrors;
    }

    /** Initializes the reporters so we can use the id to gather results
     *
     * @param conn Active Connection
     * @return List of Reporters
     * @throws SQLException
     */
    List<Reporter> initReporters(Connection conn, ReporterFactory reporterFactory, CompatibilityProxy compatibilityProxy) throws SQLException
    {
        final List<Reporter> reporterList = new ArrayList<>();

        for (ReporterOptions ro : reporterOptionsList) {
            Reporter reporter = reporterFactory.createReporter(ro.getReporterName());

            if ( reporter instanceof ReporterOptionsAware)
                ((ReporterOptionsAware) reporter).setReporterOptions(ro);

            reporter.init(conn, compatibilityProxy, reporterFactory);

            ro.setReporterObj(reporter);
            reporterList.add(reporter);
        }

        return reporterList;
    }

    /** Starts a separate thread for each Reporter to gather its results
     *
     * @param executorService
     * @param dataSource
     */
    void startReporterGatherers(ExecutorService executorService, final DataSource dataSource)
    {
        if ( this.executorService != null && !this.executorService.isShutdown())
            throw new IllegalStateException("There is already a running executor service!");

        this.executorService = executorService;

        // TODO: Implement Init-check
        // Gather each reporter results on a separate thread.
        for (ReporterOptions ro : reporterOptionsList) {
            executorService.submit(() -> {
                List<PrintStream> printStreams = new ArrayList<>();
                PrintStream fileOutStream = null;

                try (Connection conn = dataSource.getConnection()) {
                    if (ro.outputToScreen()) {
                        printStreams.add(System.out);
                        ro.getReporterObj().getOutputBuffer().setFetchSize(1);
                    }

                    if (ro.outputToFile()) {
                        fileOutStream = new PrintStream(new FileOutputStream(ro.getOutputFileName()));
                        printStreams.add(fileOutStream);
                    }

                    ro.getReporterObj().getOutputBuffer().printAvailable(conn, printStreams);
                } catch (SQLException | FileNotFoundException e) {
                    abortGathering(e);
                } finally {
                    if (fileOutStream != null)
                        fileOutStream.close();
                }
            });
        }
    }

    List<ReporterOptions> getReporterOptionsList() {
        return reporterOptionsList;
    }

    int getNumberOfReporters() { return reporterOptionsList.size(); }
}

@@ -778,980 +778,148 @@
 ger(
-List%3CString%3E reporterParams ) %7B%0A        parseReporterOptionsList(reporterParams);%0A        initReporterOptionsList();%0A    %7D%0A%0A    ReporterManager( ReporterOptions%5B%5D reporterOptions ) %7B%0A        this.reporterOptionsList = Arrays.asList(reporterOptions);%0A        initReporterOptionsList();%0A    %7D%0A%0A    private void parseReporterOptionsList( List%3CString%3E reporterParams ) %7B%0A        reporterOptionsList = new ArrayList%3C%3E();%0A        ReporterOptions reporterOptions = null;%0A%0A        for (String p : reporterParams) %7B%0A            if (reporterOptions == null %7C%7C !p.startsWith(%22-%22)) %7B%0A                reporterOptions = new ReporterOptions(p);%0A                reporterOptionsList.add(reporterOptions);%0A            %7D%0A            else%0A            if (p.startsWith(%22-o=%22)) %7B%0A                reporterOptions.setOutputFileName(p.substring(3));%0A            %7D%0A            else%0A            if (p.equals(%22-s%22)) %7B%0A                reporterOptions.forceOutputToScreen(true);%0A            %7D%0A        %7D
+ ReporterOptions%5B%5D reporterOptions ) %7B%0A        this.reporterOptionsList = Arrays.asList(reporterOptions);%0A        initReporterOptionsList();
 %0A   

Remove unnecessary logic