/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * <p>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
 *
 * <p>http://www.apache.org/licenses/LICENSE-2.0
 *
 * <p>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.vts.util;

import com.android.vts.entity.ProfilingPointEntity;
import com.android.vts.entity.ProfilingPointRunEntity;
import com.android.vts.entity.ProfilingPointSummaryEntity;
import com.android.vts.proto.VtsReportMessage.VtsProfilingRegressionMode;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import java.io.IOException;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.apache.commons.lang.StringUtils;

/** PerformanceUtil, a helper class for analyzing profiling and performance data. */
public class PerformanceUtil {
    protected static Logger logger = Logger.getLogger(PerformanceUtil.class.getName());

    private static final int MAX_BATCH_SIZE = 2000;
    private static final DecimalFormat FORMATTER;
    private static final String NAME_DELIMITER = ", ";
    private static final String OPTION_DELIMITER = "=";

    /** Initialize the decimal formatter. */
    static {
        FORMATTER = new DecimalFormat("#.##");
        FORMATTER.setRoundingMode(RoundingMode.HALF_UP);
    }

    /**
     * Creates the HTML for a table cell representing the percent change between two numbers.
     *
     * <p>Computes the percent change (after - before)/before * 100 and inserts it into a table cell
     * with the specified style. The color of the cell is white if 'after' is less than before.
     * Otherwise, the cell is colored red with opacity according to the percent change (100%+ delta
     * means 100% opacity). If the before value is 0 and the after value is positive, then the color
     * of the cell is 100% red to indicate an increase of undefined magnitude.
     *
     * @param baseline The baseline value observed.
     * @param test The value to compare against the baseline.
     * @param classNames A string containing HTML classes to apply to the table cell.
     * @param style A string containing additional CSS styles.
     * @returns An HTML string for a colored table cell containing the percent change.
     */
    public static String getPercentChangeHTML(
            double baseline,
            double test,
            String classNames,
            String style,
            VtsProfilingRegressionMode mode) {
        String pctChangeString = "0 %";
        double alpha = 0;
        double delta = test - baseline;
        if (baseline != 0) {
            double pctChange = delta / baseline;
            alpha = pctChange * 2;
            pctChangeString = FORMATTER.format(pctChange * 100) + " %";
        } else if (delta != 0) {
            // If the percent change is undefined, the cell will be solid red or white
            alpha = (int) Math.signum(delta); // get the sign of the delta (+1, 0, -1)
            pctChangeString = "";
        }
        if (mode == VtsProfilingRegressionMode.VTS_REGRESSION_MODE_DECREASING) {
            alpha = -alpha;
        }
        String color = "background-color: rgba(255, 0, 0, " + alpha + "); ";
        String html = "<td class='" + classNames + "' style='" + color + style + "'>";
        html += pctChangeString + "</td>";
        return html;
    }

    /**
     * Compares a test StatSummary to a baseline StatSummary using best-case performance.
     *
     * @param baseline The StatSummary object containing initial values to compare against
     * @param test The StatSummary object containing test values to be compared against the baseline
     * @param innerClasses Class names to apply to cells on the inside of the grid
     * @param outerClasses Class names to apply to cells on the outside of the grid
     * @param innerStyles CSS styles to apply to cells on the inside of the grid
     * @param outerStyles CSS styles to apply to cells on the outside of the grid
     * @return HTML string representing the performance of the test versus the baseline
     */
    public static String getBestCasePerformanceComparisonHTML(
            StatSummary baseline,
            StatSummary test,
            String innerClasses,
            String outerClasses,
            String innerStyles,
            String outerStyles) {
        if (test == null || baseline == null) {
            return "<td></td><td></td><td></td><td></td>";
        }
        String row = "";
        // Intensity of red color is a function of the relative (percent) change
        // in the new value compared to the previous day's. Intensity is a linear function
        // of percentage change, reaching a ceiling at 100% change (e.g. a doubling).
        row +=
                getPercentChangeHTML(
                        baseline.getBestCase(),
                        test.getBestCase(),
                        innerClasses,
                        innerStyles,
                        test.getRegressionMode());
        row += "<td class='" + innerClasses + "' style='" + innerStyles + "'>";
        row += FORMATTER.format(baseline.getBestCase());
        row += "<td class='" + innerClasses + "' style='" + innerStyles + "'>";
        row += FORMATTER.format(baseline.getMean());
        row += "<td class='" + outerClasses + "' style='" + outerStyles + "'>";
        row += FORMATTER.format(baseline.getStd()) + "</td>";
        return row;
    }

    /**
     * Updates a PerformanceSummary object with data in the specified window.
     *
     * @param testName The name of the table whose profiling vectors to retrieve.
     * @param startTime The (inclusive) start time in microseconds to scan from.
     * @param endTime The (inclusive) end time in microseconds at which to stop scanning.
     * @param selectedDevice The name of the device whose data to query for, or null for unfiltered.
     * @param summaries The list of PerformanceSummary objects to populate with data.
     * @throws IOException
     */
    public static void updatePerformanceSummary(
            String testName,
            long startTime,
            long endTime,
            String selectedDevice,
            List<PerformanceSummary> summaries) {
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        Query profilingPointQuery =
                new Query(ProfilingPointEntity.KIND)
                        .setFilter(
                                new Query.FilterPredicate(
                                        ProfilingPointEntity.TEST_NAME,
                                        Query.FilterOperator.EQUAL,
                                        testName));

        List<ProfilingPointEntity> profilingPoints = new ArrayList<>();
        for (Entity e :
                datastore
                        .prepare(profilingPointQuery)
                        .asIterable(DatastoreHelper.getLargeBatchOptions())) {
            ProfilingPointEntity pp = ProfilingPointEntity.fromEntity(e);
            if (pp == null) continue;
            profilingPoints.add(pp);
        }

        Query.Filter startFilter =
                new Query.FilterPredicate(
                        ProfilingPointSummaryEntity.START_TIME,
                        Query.FilterOperator.GREATER_THAN_OR_EQUAL,
                        startTime);
        Query.Filter endFilter =
                new Query.FilterPredicate(
                        ProfilingPointSummaryEntity.START_TIME,
                        Query.FilterOperator.LESS_THAN_OR_EQUAL,
                        endTime);
        Query.Filter timeFilter = Query.CompositeFilterOperator.and(startFilter, endFilter);

        Query.Filter deviceFilter;
        if (selectedDevice != null) {
            deviceFilter = FilterUtil.FilterKey.TARGET.getFilterForString(selectedDevice);
        } else {
            deviceFilter =
                    FilterUtil.FilterKey.TARGET.getFilterForString(ProfilingPointSummaryEntity.ALL);
        }
        deviceFilter =
                Query.CompositeFilterOperator.and(
                        deviceFilter,
                        FilterUtil.FilterKey.BRANCH.getFilterForString(
                                ProfilingPointSummaryEntity.ALL));
        Query.Filter filter = Query.CompositeFilterOperator.and(timeFilter, deviceFilter);

        Map<ProfilingPointEntity, Iterable<Entity>> asyncEntities = new HashMap<>();
        for (ProfilingPointEntity pp : profilingPoints) {
            Query profilingQuery =
                    new Query(ProfilingPointSummaryEntity.KIND)
                            .setAncestor(pp.getKey())
                            .setFilter(filter);
            asyncEntities.put(
                    pp,
                    datastore
                            .prepare(profilingQuery)
                            .asIterable(DatastoreHelper.getLargeBatchOptions()));
        }

        for (ProfilingPointEntity pp : asyncEntities.keySet()) {
            for (Entity ppSummaryEntity : asyncEntities.get(pp)) {
                ProfilingPointSummaryEntity ppSummary =
                        ProfilingPointSummaryEntity.fromEntity(ppSummaryEntity);
                if (ppSummary == null) continue;
                for (PerformanceSummary perfSummary : summaries) {
                    if (perfSummary.contains(ppSummary.getStartTime())) {
                        perfSummary.addData(pp, ppSummaryEntity);
                    }
                }
            }
        }
    }

    /**
     * Compares a test StatSummary to a baseline StatSummary using average-case performance.
     *
     * @param baseline The StatSummary object containing initial values to compare against
     * @param test The StatSummary object containing test values to be compared against the baseline
     * @param innerClasses Class names to apply to cells on the inside of the grid
     * @param outerClasses Class names to apply to cells on the outside of the grid
     * @param innerStyles CSS styles to apply to cells on the inside of the grid
     * @param outerStyles CSS styles to apply to cells on the outside of the grid
     * @return HTML string representing the performance of the test versus the baseline
     */
    public static String getAvgCasePerformanceComparisonHTML(
            StatSummary baseline,
            StatSummary test,
            String innerClasses,
            String outerClasses,
            String innerStyles,
            String outerStyles) {
        if (test == null || baseline == null) {
            return "<td></td><td></td><td></td><td></td>";
        }
        String row = "";
        // Intensity of red color is a function of the relative (percent) change
        // in the new value compared to the previous day's. Intensity is a linear function
        // of percentage change, reaching a ceiling at 100% change (e.g. a doubling).
        row +=
                getPercentChangeHTML(
                        baseline.getMean(),
                        test.getMean(),
                        innerClasses,
                        innerStyles,
                        test.getRegressionMode());
        row += "<td class='" + innerClasses + "' style='" + innerStyles + "'>";
        row += FORMATTER.format(baseline.getBestCase());
        row += "<td class='" + innerClasses + "' style='" + innerStyles + "'>";
        row += FORMATTER.format(baseline.getMean());
        row += "<td class='" + outerClasses + "' style='" + outerStyles + "'>";
        row += FORMATTER.format(baseline.getStd()) + "</td>";
        return row;
    }

    /**
     * Generates a string of the values in optionsList which have matches in the profiling entity.
     *
     * @param profilingRun The entity for a profiling point run.
     * @param optionKeys A list of keys to match against the optionsList key value pairs.
     * @return The values in optionsList whose key match a key in optionKeys.
     */
    public static String getOptionAlias(
            ProfilingPointRunEntity profilingRun, Set<String> optionKeys) {
        String name = "";
        if (profilingRun.getOptions() != null) {
            name = getOptionAlias(profilingRun.getOptions(), optionKeys);
        }
        return name;
    }

    /**
     * Generates a string of the values in optionsList which have matches in the profiling entity.
     *
     * @param optionList The list of key=value option pair strings.
     * @param optionKeys A list of keys to match against the optionsList key value pairs.
     * @return The values in optionsList whose key match a key in optionKeys.
     */
    public static String getOptionAlias(List<String> optionList, Set<String> optionKeys) {
        String name = "";
        List<String> nameSuffixes = new ArrayList<>();
        for (String optionString : optionList) {
            String[] optionParts = optionString.split(OPTION_DELIMITER);
            if (optionParts.length != 2) {
                continue;
            }
            if (optionKeys.contains(optionParts[0].trim().toLowerCase())) {
                nameSuffixes.add(optionParts[1].trim().toLowerCase());
            }
        }
        if (nameSuffixes.size() > 0) {
            StringUtils.join(nameSuffixes, NAME_DELIMITER);
            name += StringUtils.join(nameSuffixes, NAME_DELIMITER);
        }
        return name;
    }
}
