/*
 * Copyright  2000-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package tools.JUnit;

import java.io.*;
import java.text.NumberFormat;
import java.util.*;

import junit.framework.AssertionFailedError;
import junit.framework.Test;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.optional.junit.*;


/**
 * Prints plain text output of the test to a specified Writer.
 *
 * @author Stefan Bodewig
 */
public class SimpleResultFormatter implements JUnitResultFormatter {

     public static int TEST_SUCCESS = 0;
     public static int TEST_FAILURE = 1;
     public static int TEST_ERROR = 2;
     public static int TEST_UNKNOWN = 3;

    // Lets capture STDOUT and STDERR
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    ByteArrayOutputStream bErr = new ByteArrayOutputStream();

    PrintStream _out;
    PrintStream _err;
    private TestRecord testRecord;
    Collection records;

    /**
     * Formatter for timings.
     */
    private NumberFormat nf = NumberFormat.getInstance();
    /**
     * Timing helper.
     */
    private Hashtable testStarts = new Hashtable();
    /**
     * Where to write the log to.
     */
    private OutputStream out;
    /**
     * Helper to store intermediate output.
     */
    private StringWriter inner;
    /**
     * Convenience layer on top of {@link #inner inner}.
     */
    private PrintWriter wri;
    /**
     * Suppress endTest if testcase failed.
     */
    private Hashtable failed = new Hashtable();

    private String systemOutput = null;
    private String systemError = null;

    public SimpleResultFormatter() {
        inner = new StringWriter();
        wri = new PrintWriter(inner);
    }

    public void setOutput(OutputStream out) {
        this.out = out;
    }

    public void setSystemOutput(String out) {
        // We will be capturing Stdout and Stderr internally so this is
        // redundant
        //systemOutput = out;
    }

    public void setSystemError(String err) {
        // We will be capturing Stdout and Stderr internally so this is
        // redundant
        //systemError = err;
    }

    /**
     * Signals starting of a Suite of tests
     */
    public void startTestSuite(JUnitTest suite) {
        records = new ArrayList();
    }

    /**
     * The whole testsuite ended.
     */
    public void endTestSuite(JUnitTest suite) throws BuildException {
        String newLine = System.getProperty("line.separator");
        StringBuilder sb = new StringBuilder("Testsuite: ");
        sb.append(suite.getName());
        sb.append(newLine);
        sb.append("Tests run: ");
        sb.append(suite.runCount());
        sb.append(", Failures: ");
        sb.append(suite.failureCount());
        sb.append(", Errors: ");
        sb.append(suite.errorCount());
        sb.append(", Time elapsed: ");
        sb.append(nf.format(suite.getRunTime() / 1000.0));
        sb.append(" sec");
        sb.append(newLine);
        //sb.append("DEBUG: " + records.size());
        sb.append("======================================================");
        Iterator it = records.iterator();

        while (it.hasNext())
        {
            TestRecord rec = (TestRecord) it.next();
            sb.append(newLine);
            sb.append("Test: " + rec.getTestname()).append(newLine);
            sb.append("Result: " + rec.getStatusString()).append(newLine);
            float diff = rec.getEndTime() - rec.getStartTime();
            sb.append("Start time: " + rec.getStartTime()).append(newLine);
            sb.append("End time  : " + rec.getEndTime()).append(newLine);
            sb.append("Execution time: " + diff/1000).append(newLine);
            sb.append("[STDOUT]").append(newLine);
            sb.append(rec.getSysout()).append(newLine);
            sb.append("[STDERR]").append(newLine);
            sb.append(rec.getSyserr()).append(newLine);

            if (rec.isFailure())
            {
                sb.append("[EXCEPTION]").append(newLine);
                sb.append(JUnitTestRunner.getFilteredTrace(rec.getThrowable()));
                sb.append(newLine);
            }
            sb.append("======================================================");
        }



        /*
        // append the err and output streams to the log
        if (systemOutput != null && systemOutput.length() > 0) {
            sb.append("------------- Standard Output ---------------")
                .append(newLine)
                .append(systemOutput)
                .append("------------- ---------------- ---------------")
                .append(newLine);
        }

        if (systemError != null && systemError.length() > 0) {
            sb.append("------------- Standard Error -----------------")
                .append(newLine)
                .append(systemError)
                .append("------------- ---------------- ---------------")
                .append(newLine);
        }

        sb.append(newLine);
        */
        if (out != null) {
            try {
                out.write(sb.toString().getBytes());
                wri.close();
                //out.write(inner.toString().getBytes());
                out.flush();
            } catch (IOException ioex) {
                throw new BuildException("Unable to write output", ioex);
            } finally {
                if (out != System.out && out != System.err) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        // ignore
                    }
                }
            }
        }

    }

    /**
     * Interface TestListener.
     *
     * <p>A new Test is started.
     */
    public void startTest(Test t) {
        // Lets start the capture
        System.out.flush();
        System.err.flush();

        _out = System.out;
        _err = System.err;
        bOut.reset();
        bErr.reset();
        System.setOut(new PrintStream(bOut));
        System.setErr(new PrintStream(bErr));

        // Store the previous record

        testRecord = new TestRecord(t.toString());
        testRecord.setStartTime(System.currentTimeMillis());
        testStarts.put(t, new Long(System.currentTimeMillis()));
        failed.put(t, Boolean.FALSE);

    }

    /**
     * Interface TestListener.
     *
     * <p>A Test is finished.
     */
    public void endTest(Test test) {
        long endTime = System.currentTimeMillis();

        System.out.flush();
        System.err.flush();
        // Update the test record
        testRecord.setSysout(bOut.toString());
        testRecord.setSyserr(bErr.toString());
        testRecord.setEndTime(endTime);
        // If the test did not fail, record it as a success
        if (!testRecord.isFailure())
            testRecord.setStatus(TEST_SUCCESS);

        // Add it to the set
        records.add(testRecord);

        System.setOut(_out);
        System.setErr(_err);
    }

    /**
     * Interface TestListener for JUnit &gt; 3.4.
     *
     * <p>A Test failed.
     */
    public void addFailure(Test test, AssertionFailedError t) {
        //addFailure(test, (Throwable) t);
        testRecord.setStatus(TEST_FAILURE);
        testRecord.setThrowable(t);
        // Record end time now..
    }

    /**
     * Interface TestListener.
     *
     * <p>An error occured while running the test.
     */
    public void addError(Test test, Throwable t) {
        testRecord.setStatus(TEST_ERROR);
        testRecord.setThrowable(t);
    }

    /**
     * Utility class to record per test data like test name, status, start
     * and end time, STDOUT, STDERR from text execution etc.
     */
    private class TestRecord
    {
        public TestRecord(String name)
        {
            setTestname(name);
        }

        private String testname;
        private String sysout;
        private String syserr;
        private Throwable t;
        private long startTime;
        private long endTime;
        private int status;
        boolean failed = false;

        private String testUnitName;
        private String testLogicalName;

        public void setTestname(String name)
        {
            this.testname = name;
        }

        public String getTestname()
        {
            return testname;
        }

        public void setStatus(int status)
        {
            this.status = status;
            if (status == TEST_ERROR || status == TEST_FAILURE)
                failed = true;
        }

        public int getStatus()
        {
            return status;
        }

        public String getStatusString()
        {
            return (status == TEST_SUCCESS)?"SUCCESS":
                        (status == TEST_ERROR)?"ERROR":"FAILURE";
        }

        public boolean isFailure()
        {
            return failed;
        }

        public String getSysout()
        {
            return sysout;
        }

        public void setSysout(String sysout)
        {
            this.sysout = sysout;
        }

        public String getSyserr()
        {
            return syserr;
        }

        public void setSyserr(String syserr)
        {
            this.syserr = syserr;
        }

        public Throwable getThrowable()
        {
            return t;
        }

        public void setThrowable(Throwable t)
        {
            this.t = t;
        }

       public long getStartTime()
        {
            return startTime;
        }

        public void setStartTime(long startTime)
        {
            this.startTime = startTime;
        }

        public long getEndTime()
        {
            return endTime;
        }

        public void setEndTime(long endTime)
        {
            this.endTime = endTime;
        }

    }



} // PlainJUnitResultFormatter
