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.extensions.StatelessTestsetInfoFileReportEventListener;
import org.apache.maven.surefire.api.report.ReporterException;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.List;

import static org.apache.maven.plugin.surefire.report.FileReporterUtils.stripIllegalFilenameChars;
import static org.apache.maven.surefire.shared.utils.StringUtils.isNotBlank;

/**
 * Base class for file reporters.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @author Kristian Rosenvold
 */
public class FileReporter
        extends StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats>
{
    private final boolean usePhrasedFileName;
    private final boolean usePhrasedClassNameInRunning;
    private final boolean usePhrasedClassNameInTestCaseSummary;

    public FileReporter( File reportsDirectory, String reportNameSuffix, Charset encoding, boolean usePhrasedFileName,
                         boolean usePhrasedClassNameInRunning, boolean usePhrasedClassNameInTestCaseSummary )
    {
        super( reportsDirectory, reportNameSuffix, encoding );
        this.usePhrasedFileName = usePhrasedFileName;
        this.usePhrasedClassNameInRunning = usePhrasedClassNameInRunning;
        this.usePhrasedClassNameInTestCaseSummary = usePhrasedClassNameInTestCaseSummary;
    }

    static File getReportFile( File reportsDirectory, String reportEntryName, String reportNameSuffix,
                               String fileExtension )
    {
        String fileName =
                reportEntryName + ( isNotBlank( reportNameSuffix ) ? "-" + reportNameSuffix : "" ) + fileExtension;
        return new File( reportsDirectory, stripIllegalFilenameChars( fileName ) );
    }

    @Override
    public void testSetCompleted( WrappedReportEntry report, TestSetStats testSetStats, List<String> testResults )
    {
        File reportFile = getReportFile( getReportsDirectory(),
                                         usePhrasedFileName ? report.getReportSourceName() : report.getSourceName(),
                                         getReportNameSuffix(),
                                         ".txt" );

        File reportDir = reportFile.getParentFile();

        // noinspection ResultOfMethodCallIgnored
        reportDir.mkdirs();

        try ( BufferedWriter writer = createFileReporterWriter( reportFile, getEncoding() ) )
        {
            writer.write( "-------------------------------------------------------------------------------" );
            writer.newLine();

            String tesSet = usePhrasedClassNameInRunning ? report.getReportSourceName() : report.getSourceName();
            writer.write( "Test set: " + tesSet );
            writer.newLine();

            writer.write( "-------------------------------------------------------------------------------" );
            writer.newLine();

            writer.write( testSetStats.getTestSetSummary( report, usePhrasedClassNameInTestCaseSummary ) );
            writer.newLine();
            for ( String testResult : testResults )
            {
                writer.write( testResult );
                writer.newLine();
            }
        }
        catch ( IOException e )
        {
            throw new ReporterException( "Unable to create file for report: " + e.getLocalizedMessage(), e );
        }
    }

    private static BufferedWriter createFileReporterWriter( File reportFile, Charset encoding )
            throws FileNotFoundException
    {
        return new BufferedWriter( new OutputStreamWriter( new FileOutputStream( reportFile ), encoding ), 64 * 1024 );
    }
}
