package org.apache.maven.plugin.surefire.report;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import org.apache.maven.surefire.shared.utils.logging.MessageBuilder;
import org.apache.maven.surefire.api.report.ReportEntry;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import static org.apache.maven.surefire.shared.utils.logging.MessageUtils.buffer;
import static org.apache.maven.surefire.api.report.CategorizedReportEntry.GROUP_PREFIX;

/**
 * Maintains per-thread test result state. Not thread safe.
 */
public class TestSetStats
{
    private static final String TESTS = "Tests ";
    private static final String RUN = "run: ";
    private static final String TESTS_RUN = "Tests run: ";
    private static final String FAILURES = "Failures: ";
    private static final String ERRORS = "Errors: ";
    private static final String SKIPPED = "Skipped: ";
    private static final String FAILURE_MARKER = " <<< FAILURE!";
    private static final String IN_MARKER = " - in ";
    private static final String COMMA = ", ";

    private final Queue<WrappedReportEntry> reportEntries = new ConcurrentLinkedQueue<>();

    private final boolean trimStackTrace;

    private final boolean plainFormat;

    private long testSetStartAt;

    private long testStartAt;

    private int completedCount;

    private int errors;

    private int failures;

    private int skipped;

    private long lastStartAt;

    public TestSetStats( boolean trimStackTrace, boolean plainFormat )
    {
        this.trimStackTrace = trimStackTrace;
        this.plainFormat = plainFormat;
    }

    public int getElapsedSinceTestSetStart()
    {
        return testSetStartAt > 0 ? (int) ( System.currentTimeMillis() - testSetStartAt ) : 0;
    }

    public int getElapsedSinceLastStart()
    {
        return lastStartAt > 0 ? (int) ( System.currentTimeMillis() - lastStartAt ) : 0;
    }

    public void testSetStart()
    {
        testSetStartAt = System.currentTimeMillis();
        lastStartAt = testSetStartAt;
    }

    public void testStart()
    {
        testStartAt = System.currentTimeMillis();
        lastStartAt = testStartAt;
    }

    private void finishTest( WrappedReportEntry reportEntry )
    {
        reportEntries.add( reportEntry );
        incrementCompletedCount();
        // SUREFIRE-398 skipped tests call endTest without calling testStarting
        // if startTime = 0, set it to endTime, so the diff will be 0
        if ( testStartAt == 0 )
        {
            testStartAt = System.currentTimeMillis();
        }
    }

    public void testSucceeded( WrappedReportEntry reportEntry )
    {
        finishTest( reportEntry );
    }

    public void testError( WrappedReportEntry reportEntry )
    {
        errors += 1;
        finishTest( reportEntry );
    }

    public void testFailure( WrappedReportEntry reportEntry )
    {
        failures += 1;
        finishTest( reportEntry );
    }

    public void testSkipped( WrappedReportEntry reportEntry )
    {
        skipped += 1;
        finishTest( reportEntry );
    }

    public void reset()
    {
        completedCount = 0;
        errors = 0;
        failures = 0;
        skipped = 0;

        for ( WrappedReportEntry entry : reportEntries )
        {
            entry.getStdout().free();
            entry.getStdErr().free();
        }

        reportEntries.clear();
    }

    public int getCompletedCount()
    {
        return completedCount;
    }

    public int getErrors()
    {
        return errors;
    }

    public int getFailures()
    {
        return failures;
    }

    public int getSkipped()
    {
        return skipped;
    }

    private void incrementCompletedCount()
    {
        completedCount += 1;
    }

    public String getTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName )
    {
        String summary = TESTS_RUN + completedCount
                                 + COMMA
                                 + FAILURES + failures
                                 + COMMA
                                 + ERRORS + errors
                                 + COMMA
                                 + SKIPPED + skipped
                                 + COMMA
                                 + reportEntry.getElapsedTimeVerbose();

        if ( failures > 0 || errors > 0 )
        {
            summary += FAILURE_MARKER;
        }

        summary += IN_MARKER;
        summary += phrasedClassName ? reportEntry.getReportNameWithGroup() : reportEntry.getNameWithGroup();

        return summary;
    }

    public String getColoredTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName )
    {
        final boolean isSuccessful = failures == 0 && errors == 0 && skipped == 0;
        final boolean isFailure = failures > 0;
        final boolean isError = errors > 0;
        final boolean isFailureOrError = isFailure | isError;
        final boolean isSkipped = skipped > 0;
        final  MessageBuilder builder = buffer();
        if ( isSuccessful )
        {
            if ( completedCount == 0 )
            {
                builder.strong( TESTS_RUN ).strong( completedCount );
            }
            else
            {
                builder.success( TESTS_RUN ).success( completedCount );
            }
        }
        else
        {
            if ( isFailureOrError )
            {
                builder.failure( TESTS ).strong( RUN ).strong( completedCount );
            }
            else
            {
                builder.warning( TESTS ).strong( RUN ).strong( completedCount );
            }
        }
        builder.a( COMMA );
        if ( isFailure )
        {
            builder.failure( FAILURES ).failure( failures );
        }
        else
        {
            builder.a( FAILURES ).a( failures );
        }
        builder.a( COMMA );
        if ( isError )
        {
            builder.failure( ERRORS ).failure( errors );
        }
        else
        {
            builder.a( ERRORS ).a( errors );
        }
        builder.a( COMMA );
        if ( isSkipped )
        {
            builder.warning( SKIPPED ).warning( skipped );
        }
        else
        {
            builder.a( SKIPPED ).a( skipped );
        }
        builder.a( COMMA )
                .a( reportEntry.getElapsedTimeVerbose() );
        if ( isFailureOrError )
        {
            builder.failure( FAILURE_MARKER );
        }
        builder.a( IN_MARKER );
        return concatenateWithTestGroup( builder, reportEntry, phrasedClassName );
    }

    public List<String> getTestResults()
    {
        List<String> result = new ArrayList<>();
        for ( WrappedReportEntry testResult : reportEntries )
        {
            if ( testResult.isErrorOrFailure() )
            {
                result.add( testResult.getOutput( trimStackTrace ) );
            }
            else if ( plainFormat && testResult.isSkipped() )
            {
                result.add( testResult.getSourceName() + " skipped" );
            }
            else if ( plainFormat && testResult.isSucceeded() )
            {
                result.add( testResult.getElapsedTimeSummary() );
            }
        }
        // This should be Map with an enum and the enums will be displayed with colors on console.
        return result;
    }

    public Collection<WrappedReportEntry> getReportEntries()
    {
        return reportEntries;
    }

    /**
     * Append the test set message for a report.
     * e.g. "org.foo.BarTest ( of group )" or phrased text "test class description ( of group )".
     *
     * @param builder    MessageBuilder with preceded text inside
     * @param report     report whose test set is starting
     * @return the message
     */
    static String concatenateWithTestGroup( MessageBuilder builder, ReportEntry report, boolean phrasedClassName )
    {
        if ( phrasedClassName )
        {
            return builder.strong( report.getReportNameWithGroup() )
                    .toString();
        }
        else
        {
            String testClass = report.getNameWithGroup();
            int indexOfGroup = testClass.indexOf( GROUP_PREFIX );
            int delimiter = testClass.lastIndexOf( '.', indexOfGroup == -1 ? testClass.length() : indexOfGroup );
            String pkg = testClass.substring( 0, 1 + delimiter );
            String cls = testClass.substring( 1 + delimiter );
            return builder.a( pkg )
                    .strong( cls )
                    .toString();
        }
    }
}
