package org.elasticsearch.junit.listeners;

import com.carrotsearch.randomizedtesting.RandomizedContext;
import com.carrotsearch.randomizedtesting.ReproduceErrorMessageBuilder;
import com.carrotsearch.randomizedtesting.TraceFormatting;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.ElasticsearchTestCase;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

/**
 * A {@link RunListener} that emits to {@link System#err} a string with command
 * line parameters allowing quick test re-run under MVN command line.
 */
public class ReproduceInfoPrinter extends RunListener {

    protected final ESLogger logger = Loggers.getLogger(ElasticsearchTestCase.class);

    @Override
    public void testStarted(Description description) throws Exception {
        logger.info("Test {} started", description.getDisplayName());
    }

    @Override
    public void testFinished(Description description) throws Exception {
        logger.info("Test {} finished", description.getDisplayName());
    }

    @Override
    public void testFailure(Failure failure) throws Exception {
        // Ignore assumptions.
        if (failure.getException() instanceof AssumptionViolatedException) {
            return;
        }

        final Description d = failure.getDescription();
        final StringBuilder b = new StringBuilder();
        b.append("FAILURE  : ").append(d.getDisplayName()).append("\n");
        b.append("REPRODUCE WITH  : mvn test");
        new MavenMessageBuilder(b).appendAllOpts(failure.getDescription());

        b.append("\n");
        b.append("Throwable:\n");
        if (failure.getException() != null) {
            TraceFormatting traces = new TraceFormatting();
            try {
                traces = RandomizedContext.current().getRunner().getTraceFormatting();
            } catch (IllegalStateException e) {
                // Ignore if no context.
            }
            traces.formatThrowable(b, failure.getException());
        }
        logger.error(b.toString());
    }

    private static class MavenMessageBuilder extends ReproduceErrorMessageBuilder {

        public MavenMessageBuilder(StringBuilder b) {
            super(b);
        }

        /**
         * Append a single VM option.
         */
        public ReproduceErrorMessageBuilder appendOpt(String sysPropName, String value) {
            if (sysPropName.equals("tests.iters")) { // we don't want the iters to be in there!
                return this;
            }
            return super.appendOpt(sysPropName, value);
        }
    }
}

@@ -229,16 +229,64 @@
 atting;%0A
+import org.elasticsearch.ElasticsearchTestCase;%0A
 import o
@@ -380,56 +380,8 @@
 rs;%0A
-import org.elasticsearch.ElasticsearchTestCase;%0A
 impo
@@ -565,16 +565,42 @@
 tener;%0A%0A
+import java.util.Arrays;%0A%0A
 /**%0A * A
@@ -2397,32 +2397,233 @@
 (b);%0A        %7D%0A%0A
+        @Override%0A        public ReproduceErrorMessageBuilder appendAllOpts(Description description) %7B%0A            super.appendAllOpts(description);%0A            return appendESProperties();%0A        %7D%0A%0A
         /**%0A    
@@ -2959,20 +2959,467 @@
 ;%0A        %7D%0A
+        %0A        public ReproduceErrorMessageBuilder appendESProperties() %7B%0A            for (String sysPropName : Arrays.asList(%0A                %22es.logger.level%22, %22es.node.mode%22, %22es.node.local%22)) %7B%0A              if (System.getProperty(sysPropName) != null && !System.getProperty(sysPropName).isEmpty()) %7B%0A                appendOpt(sysPropName, System.getProperty(sysPropName));%0A              %7D%0A            %7D%0A            return this;%0A          %7D%0A
     %7D%0A%7D%0A

Print '-Des.x.y' properties in reproduce line