/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 com.android.compatibility.common.tradefed.result.suite;

import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.util.DeviceInfo;
import com.android.compatibility.common.util.ResultHandler;
import com.android.compatibility.common.util.ResultUploader;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.ILogSaver;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ITestSummaryListener;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.LogFile;
import com.android.tradefed.result.LogFileSaver;
import com.android.tradefed.result.SnapshotInputStreamSource;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.result.TestSummary;
import com.android.tradefed.result.suite.IFormatterGenerator;
import com.android.tradefed.result.suite.SuiteResultReporter;
import com.android.tradefed.result.suite.XmlFormattedGeneratorReporter;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.StreamUtil;
import com.android.tradefed.util.ZipUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

/**
 * Extension of {@link XmlFormattedGeneratorReporter} and {@link SuiteResultReporter} to handle
 * Compatibility specific format and operations.
 */
@OptionClass(alias = "result-reporter")
public class CertificationSuiteResultReporter extends XmlFormattedGeneratorReporter
        implements ITestSummaryListener {

    public static final String LATEST_LINK_NAME = "latest";
    public static final String SUMMARY_FILE = "invocation_summary.txt";
    public static final String HTLM_REPORT_NAME = "test_result.html";
    public static final String REPORT_XSL_FILE_NAME = "compatibility_result.xsl";
    public static final String FAILURE_REPORT_NAME = "test_result_failures_suite.html";
    public static final String FAILURE_XSL_FILE_NAME = "compatibility_failures.xsl";

    public static final String BUILD_FINGERPRINT = "build_fingerprint";

    @Option(name = "result-server", description = "Server to publish test results.")
    private String mResultServer;

    @Option(
            name = "disable-result-posting",
            description ="Disable result posting into report server."
    )
    private boolean mDisableResultPosting = false;

    @Option(name = "include-test-log-tags", description = "Include test log tags in report.")
    private boolean mIncludeTestLogTags = false;

    @Option(name = "use-log-saver", description = "Also saves generated result with log saver")
    private boolean mUseLogSaver = false;

    @Option(name = "compress-logs", description = "Whether logs will be saved with compression")
    private boolean mCompressLogs = true;

    public static final String INCLUDE_HTML_IN_ZIP = "html-in-zip";
    @Option(name = INCLUDE_HTML_IN_ZIP,
            description = "Whether failure summary report is included in the zip fie.")
    private boolean mIncludeHtml = false;

    @Option(
            name = "result-attribute",
            description =
                    "Extra key-value pairs to be added as attributes and corresponding values "
                            + "of the \"Result\" tag in the result XML.")
    private Map<String, String> mResultAttributes = new HashMap<String, String>();

    private CompatibilityBuildHelper mBuildHelper;

    /** The directory containing the results */
    private File mResultDir = null;
    /** The directory containing the logs */
    private File mLogDir = null;

    private ResultUploader mUploader;

    /** LogFileSaver to copy the file to the CTS results folder */
    private LogFileSaver mTestLogSaver;

    private Map<LogFile, InputStreamSource> mPreInvocationLogs = new HashMap<>();
    /** Invocation level Log saver to receive when files are logged */
    private ILogSaver mLogSaver;

    private String mReferenceUrl;

    private Map<String, String> mLoggedFiles;

    private static final String[] RESULT_RESOURCES = {
        "compatibility_result.css",
        "compatibility_result.xsl",
        "logo.png"
    };

    public CertificationSuiteResultReporter() {
        super();
        mLoggedFiles = new LinkedHashMap<>();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final void invocationStarted(IInvocationContext context) {
        super.invocationStarted(context);

        if (mBuildHelper == null) {
            mBuildHelper = new CompatibilityBuildHelper(getPrimaryBuildInfo());
        }
        if (mResultDir == null) {
            initializeResultDirectories();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void testLog(String name, LogDataType type, InputStreamSource stream) {
        if (name.endsWith(DeviceInfo.FILE_SUFFIX)) {
            // Handle device info file case
            testLogDeviceInfo(name, stream);
            return;
        }
        if (mTestLogSaver == null) {
            LogFile info = new LogFile(name, null, type);
            mPreInvocationLogs.put(
                    info, new SnapshotInputStreamSource(name, stream.createInputStream()));
            return;
        }
        try {
            File logFile = null;
            if (mCompressLogs) {
                try (InputStream inputStream = stream.createInputStream()) {
                    logFile = mTestLogSaver.saveAndGZipLogData(name, type, inputStream);
                }
            } else {
                try (InputStream inputStream = stream.createInputStream()) {
                    logFile = mTestLogSaver.saveLogData(name, type, inputStream);
                }
            }
            CLog.d("Saved logs for %s in %s", name, logFile.getAbsolutePath());
        } catch (IOException e) {
            CLog.e("Failed to write log for %s", name);
            CLog.e(e);
        }
    }

    /** Write device-info files to the result, invoked only by the master result reporter */
    private void testLogDeviceInfo(String name, InputStreamSource stream) {
        try {
            File ediDir = new File(mResultDir, DeviceInfo.RESULT_DIR_NAME);
            ediDir.mkdirs();
            File ediFile = new File(ediDir, name);
            if (!ediFile.exists()) {
                // only write this file to the results if not already present
                FileUtil.writeToFile(stream.createInputStream(), ediFile);
            }
        } catch (IOException e) {
            CLog.w("Failed to write device info %s to result", name);
            CLog.e(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void testLogSaved(String dataName, LogDataType dataType, InputStreamSource dataStream,
            LogFile logFile) {
        if (mIncludeTestLogTags) {
            switch (dataType) {
                case BUGREPORT:
                case LOGCAT:
                case PNG:
                    mLoggedFiles.put(dataName, logFile.getUrl());
                    break;
                default:
                    // Do nothing
                    break;
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void putSummary(List<TestSummary> summaries) {
        for (TestSummary summary : summaries) {
            if (mReferenceUrl == null && summary.getSummary().getString() != null) {
                mReferenceUrl = summary.getSummary().getString();
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setLogSaver(ILogSaver saver) {
        mLogSaver = saver;
    }

    /**
     * Create directory structure where results and logs will be written.
     */
    private void initializeResultDirectories() {
        CLog.d("Initializing result directory");
        try {
            mResultDir = mBuildHelper.getResultDir();
            if (mResultDir != null) {
                mResultDir.mkdirs();
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }

        if (mResultDir == null) {
            throw new RuntimeException("Result Directory was not created");
        }
        if (!mResultDir.exists()) {
            throw new RuntimeException("Result Directory was not created: " +
                    mResultDir.getAbsolutePath());
        }

        CLog.d("Results Directory: %s", mResultDir.getAbsolutePath());

        mUploader = new ResultUploader(mResultServer, mBuildHelper.getSuiteName());
        try {
            mLogDir = mBuildHelper.getInvocationLogDir();
        } catch (FileNotFoundException e) {
            CLog.e(e);
        }
        if (mLogDir != null && mLogDir.mkdirs()) {
            CLog.d("Created log dir %s", mLogDir.getAbsolutePath());
        }
        if (mLogDir == null || !mLogDir.exists()) {
            throw new IllegalArgumentException(String.format("Could not create log dir %s",
                    mLogDir.getAbsolutePath()));
        }
        // During sharding, we reach here before invocationStarted is called so the log_saver will
        // be null at that point.
        if (mTestLogSaver == null) {
            mTestLogSaver = new LogFileSaver(mLogDir);
            // Log all the early logs from before init.
            for (LogFile earlyLog : mPreInvocationLogs.keySet()) {
                try (InputStreamSource source = mPreInvocationLogs.get(earlyLog)) {
                    testLog(earlyLog.getPath(), earlyLog.getType(), source);
                }
            }
            mPreInvocationLogs.clear();
        }
    }

    @Override
    public IFormatterGenerator createFormatter() {
        return new CertificationResultXml(
                mBuildHelper.getSuiteName(),
                mBuildHelper.getSuiteVersion(),
                mBuildHelper.getSuitePlan(),
                mBuildHelper.getSuiteBuild(),
                mReferenceUrl,
                getLogUrl(),
                mResultAttributes);
    }

    @Override
    public void preFormattingSetup(IFormatterGenerator formater) {
        super.preFormattingSetup(formater);
        // Log the summary
        TestSummary summary = getSummary();
        try {
            File summaryFile = new File(mResultDir, SUMMARY_FILE);
            FileUtil.writeToFile(summary.getSummary().toString(), summaryFile);
        } catch (IOException e) {
            CLog.e("Failed to save the summary.");
            CLog.e(e);
        }

        copyDynamicConfigFiles();
        copyFormattingFiles(mResultDir, mBuildHelper.getSuiteName());
    }

    @Override
    public File createResultDir() throws IOException {
        return mResultDir;
    }

    @Override
    public void postFormattingStep(File resultDir, File reportFile) {
        super.postFormattingStep(resultDir,reportFile);

        createChecksum(
                resultDir,
                getMergedTestRunResults(),
                getPrimaryBuildInfo().getBuildAttributes().get(BUILD_FINGERPRINT));

        File report = createReport(reportFile);
        if (report != null) {
            CLog.i("Viewable report: %s", report.getAbsolutePath());
        }
        File failureReport = null;
        if (mIncludeHtml) {
            // Create the html report before the zip file.
            failureReport = createFailureReport(reportFile);
        }
        File zippedResults = zipResults(mResultDir);
        if (!mIncludeHtml) {
            // Create failure report after zip file so extra data is not uploaded
            failureReport = createFailureReport(reportFile);
        }
        try {
            if (failureReport.exists()) {
                CLog.i("Test Result: %s", failureReport.getCanonicalPath());
            } else {
                CLog.i("Test Result: %s", reportFile.getCanonicalPath());
            }
            Path latestLink = createLatestLinkDirectory(mResultDir.toPath());
            if (latestLink != null) {
                CLog.i("Latest results link: " + latestLink.toAbsolutePath());
            }

            latestLink = createLatestLinkDirectory(mLogDir.toPath());
            if (latestLink != null) {
                CLog.i("Latest logs link: " + latestLink.toAbsolutePath());
            }

            saveLog(reportFile, zippedResults);
        } catch (IOException e) {
            CLog.e("Error when handling the post processing of results file:");
            CLog.e(e);
        }

        uploadResult(reportFile);
    }

    /**
     * Return the path in which log saver persists log files or null if
     * logSaver is not enabled.
     */
    private String getLogUrl() {
        if (!mUseLogSaver || mLogSaver == null) {
            return null;
        }

        return mLogSaver.getLogReportDir().getUrl();
    }

    /**
     * Update the "latest" symlink to the newest result directory. CTS specific.
     */
    private Path createLatestLinkDirectory(Path directory) {
        Path link = null;

        Path parent = directory.getParent();

        if (parent != null) {
            link = parent.resolve(LATEST_LINK_NAME);
            try {
                // if latest already exists, we have to remove it before creating
                Files.deleteIfExists(link);
                Files.createSymbolicLink(link, directory);
            } catch (IOException ioe) {
                CLog.e("Exception while attempting to create 'latest' link to: [%s]",
                    directory);
                CLog.e(ioe);
                return null;
            } catch (UnsupportedOperationException uoe) {
                CLog.e("Failed to create 'latest' symbolic link - unsupported operation");
                return null;
            }
        }
        return link;
    }

    /**
     * move the dynamic config files to the results directory
     */
    private void copyDynamicConfigFiles() {
        File configDir = new File(mResultDir, "config");
        if (!configDir.exists() && !configDir.mkdir()) {
            CLog.w(
                    "Failed to make dynamic config directory \"%s\" in the result.",
                    configDir.getAbsolutePath());
        }

        Set<String> uniqueModules = new HashSet<>();
        // Check each build of the invocation, in case of multi-device invocation.
        for (IBuildInfo buildInfo : getInvocationContext().getBuildInfos()) {
            CompatibilityBuildHelper helper = new CompatibilityBuildHelper(buildInfo);
            Map<String, File> dcFiles = helper.getDynamicConfigFiles();
            for (String moduleName : dcFiles.keySet()) {
                File srcFile = dcFiles.get(moduleName);
                if (!uniqueModules.contains(moduleName)) {
                    // have not seen config for this module yet, copy into result
                    File destFile = new File(configDir, moduleName + ".dynamic");
                    if (destFile.exists()) {
                        continue;
                    }
                    try {
                        FileUtil.copyFile(srcFile, destFile);
                        uniqueModules.add(moduleName); // Add to uniqueModules if copy succeeds
                    } catch (IOException e) {
                        CLog.w("Failure when copying config file \"%s\" to \"%s\" for module %s",
                                srcFile.getAbsolutePath(), destFile.getAbsolutePath(), moduleName);
                        CLog.e(e);
                    }
                }
                FileUtil.deleteFile(srcFile);
            }
        }
    }

    /**
     * Copy the xml formatting files stored in this jar to the results directory. CTS specific.
     *
     * @param resultsDir
     */
    private void copyFormattingFiles(File resultsDir, String suiteName) {
        for (String resultFileName : RESULT_RESOURCES) {
            InputStream configStream = CertificationResultXml.class.getResourceAsStream(
                    String.format("/report/%s-%s", suiteName, resultFileName));
            if (configStream == null) {
                // If suite specific files are not available, fallback to common.
                configStream = CertificationResultXml.class.getResourceAsStream(
                    String.format("/report/%s", resultFileName));
            }
            if (configStream != null) {
                File resultFile = new File(resultsDir, resultFileName);
                try {
                    FileUtil.writeToFile(configStream, resultFile);
                } catch (IOException e) {
                    CLog.w("Failed to write %s to file", resultFileName);
                }
            } else {
                CLog.w("Failed to load %s from jar", resultFileName);
            }
        }
    }

    /**
     * When enabled, save log data using log saver
     */
    private void saveLog(File resultFile, File zippedResults) throws IOException {
        if (!mUseLogSaver) {
            return;
        }

        FileInputStream fis = null;
        LogFile logFile = null;
        try {
            fis = new FileInputStream(resultFile);
            logFile = mLogSaver.saveLogData("log-result", LogDataType.XML, fis);
            CLog.d("Result XML URL: %s", logFile.getUrl());
            logReportFiles(getConfiguration(), resultFile, resultFile.getName(), LogDataType.XML);
        } catch (IOException ioe) {
            CLog.e("error saving XML with log saver");
            CLog.e(ioe);
        } finally {
            StreamUtil.close(fis);
        }
        // Save the full results folder.
        if (zippedResults != null) {
            FileInputStream zipResultStream = null;
            try {
                zipResultStream = new FileInputStream(zippedResults);
                logFile = mLogSaver.saveLogData("results", LogDataType.ZIP, zipResultStream);
                CLog.d("Result zip URL: %s", logFile.getUrl());
                logReportFiles(getConfiguration(), zippedResults, "results", LogDataType.ZIP);
            } finally {
                StreamUtil.close(zipResultStream);
            }
        }
    }

    /**
     * Zip the contents of the given results directory. CTS specific.
     *
     * @param resultsDir
     */
    private static File zipResults(File resultsDir) {
        File zipResultFile = null;
        try {
            // create a file in parent directory, with same name as resultsDir
            zipResultFile = new File(resultsDir.getParent(), String.format("%s.zip",
                    resultsDir.getName()));
            ZipUtil.createZip(resultsDir, zipResultFile);
        } catch (IOException e) {
            CLog.w("Failed to create zip for %s", resultsDir.getName());
        }
        return zipResultFile;
    }

    /**
     * When enabled, upload the result to a server. CTS specific.
     */
    private void uploadResult(File resultFile) {
        if (mResultServer != null && !mResultServer.trim().isEmpty() && !mDisableResultPosting) {
            try {
                CLog.d("Result Server: %d", mUploader.uploadResult(resultFile, mReferenceUrl));
            } catch (IOException ioe) {
                CLog.e("IOException while uploading result.");
                CLog.e(ioe);
            }
        }
    }

    /** Generate html report. */
    private File createReport(File inputXml) {
        File report = new File(inputXml.getParentFile(), HTLM_REPORT_NAME);
        try (InputStream xslStream =
                        new FileInputStream(
                                new File(inputXml.getParentFile(), REPORT_XSL_FILE_NAME));
                OutputStream outputStream = new FileOutputStream(report)) {
            Transformer transformer =
                    TransformerFactory.newInstance().newTransformer(new StreamSource(xslStream));
            transformer.transform(new StreamSource(inputXml), new StreamResult(outputStream));
        } catch (IOException | TransformerException ignored) {
            CLog.e(ignored);
            FileUtil.deleteFile(report);
            return null;
        }
        return report;
    }

    /**
     * Generate html report listing an failed tests. CTS specific.
     */
    private File createFailureReport(File inputXml) {
        File failureReport = new File(inputXml.getParentFile(), FAILURE_REPORT_NAME);
        try (InputStream xslStream = ResultHandler.class.getResourceAsStream(
                String.format("/report/%s", FAILURE_XSL_FILE_NAME));
             OutputStream outputStream = new FileOutputStream(failureReport)) {

            Transformer transformer = TransformerFactory.newInstance().newTransformer(
                    new StreamSource(xslStream));
            transformer.transform(new StreamSource(inputXml), new StreamResult(outputStream));
        } catch (IOException | TransformerException ignored) {
            CLog.e(ignored);
        }
        return failureReport;
    }

    /**
     * Generates a checksum files based on the results.
     */
    private void createChecksum(File resultDir, Collection<TestRunResult> results,
            String buildFingerprint) {
        CertificationChecksumHelper.tryCreateChecksum(resultDir, results, buildFingerprint);
    }

    /** Re-log a result file to all reporters so they are aware of it. */
    private void logReportFiles(
            IConfiguration configuration, File resultFile, String dataName, LogDataType type) {
        if (configuration == null) {
            return;
        }
        List<ITestInvocationListener> listeners = configuration.getTestInvocationListeners();
        try (FileInputStreamSource source = new FileInputStreamSource(resultFile)) {
            for (ITestInvocationListener listener : listeners) {
                if (listener.equals(this)) {
                    // Avoid logging agaisnt itself
                    continue;
                }
                listener.testLog(dataName, type, source);
            }
        }
    }
}
