/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors: IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.test.internal.performance;

import java.io.PrintStream;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.test.internal.performance.data.DataPoint;
import org.eclipse.test.internal.performance.data.Dim;
import org.eclipse.test.internal.performance.data.Sample;
import org.eclipse.test.internal.performance.db.DB;
import org.eclipse.test.internal.performance.db.Variations;
import org.eclipse.test.internal.performance.eval.StatisticsSession;
import org.eclipse.test.internal.performance.eval.StatisticsUtil;
import org.eclipse.test.internal.performance.eval.StatisticsUtil.Percentile;
import org.eclipse.test.performance.Dimension;
import org.eclipse.test.performance.PerformanceMeter;

public abstract class InternalPerformanceMeter extends PerformanceMeter {

    private static class DimensionComparator implements Comparator<Dim> {

        @Override
        public int compare(Dim o1, Dim o2) {
            return o1.getId() - o2.getId();
        }

    }

    public static final int       AVERAGE                            = -3;
    public static final int       SIZE                               = -4;
    public static final int       STDEV                              = -5;
    public static final int       BEFORE                             = 0;
    public static final int       AFTER                              = 1;

    protected static final String VERBOSE_PERFORMANCE_METER_PROPERTY = "InternalPrintPerformanceResults"; //$NON-NLS-1$

    private String                fScenarioId;

    private String                fShortName;
    private Dimension[]           fSummaryDimensions;
    private boolean               fSummaryIsGlobal;
    private int                   fCommentType;
    private String                fComment;

    public InternalPerformanceMeter(String scenarioId) {
        fScenarioId = scenarioId;
    }

    @Override
    public void dispose() {
        fScenarioId = null;
    }

    public abstract Sample getSample();

    /**
     * Answer the scenario ID.
     * 
     * @return the scenario ID
     */
    public String getScenarioName() {
        return fScenarioId;
    }

    @Override
    public void commit() {
        Sample sample = getSample();
        if (sample != null) {
            if (fSummaryDimensions != null) {
                sample.tagAsSummary(fSummaryIsGlobal, fShortName, fSummaryDimensions, fCommentType, fComment);
            } else if (this.fComment != null) {
                sample.setComment(this.fCommentType, this.fComment);
            }
            Variations variations = PerformanceTestPlugin.getVariations();
            if (variations != null)
                DB.store(variations, sample);
            if (!DB.isActive() || System.getProperty(VERBOSE_PERFORMANCE_METER_PROPERTY) != null) {
                printSample(System.out, sample);
                // printSampleCSV(System.out, sample);
            }
        }
    }

    private void printSample(PrintStream ps, Sample sample) {
        ps.print("Scenario '" + getScenarioName() + "' "); //$NON-NLS-1$ //$NON-NLS-2$
        DataPoint[] dataPoints = sample.getDataPoints();
        if (dataPoints.length > 0) {
            StatisticsSession s = new StatisticsSession(dataPoints);
            Dim[] dimensions = dataPoints[0].getDimensions();
            Arrays.sort(dimensions, new DimensionComparator());
            if (dimensions.length > 0) {
                List<Dim> badDimensions = new ArrayList<>();
                long n = s.getCount(dimensions[0]);
                MessageFormat format = new MessageFormat("({0,number,percent} in [{1}, {2}])"); //$NON-NLS-1$

                String spaces = "                                                                                                       "; //$NON-NLS-1$

                ps.println("(average over " + n + " samples):"); //$NON-NLS-1$ //$NON-NLS-2$
                for (Dim dimension : dimensions) {
                    double mean = s.getAverage(dimension);

                    String nameString = "  " + dimension.getName() + ":"; //$NON-NLS-1$ //$NON-NLS-2$
                    String meanString = dimension.getDisplayValue(mean);
                    int align = firstNonDigit(meanString);
                    int endIndex = 30 - align - nameString.length();
                    if (endIndex > 0)
                        meanString = spaces.substring(0, endIndex) + meanString;

                    align = nameString.length() + meanString.length();

                    Percentile percentile = StatisticsUtil.T95;
                    double[] confidenceInterval = s.getConfidenceInterval(dimension, percentile);

                    StringBuffer printBuffer;
                    if (n <= 2) {
                        printBuffer = new StringBuffer(" (no confidence)"); //$NON-NLS-1$
                    } else {
                        printBuffer = new StringBuffer();
                        int ns = align;
                        while (ns++ < 40)
                            printBuffer.append(' ');
                        printBuffer
                                .append(format.format(new Object[] { new Double(percentile.inside()),
                                        dimension.getDisplayValue(confidenceInterval[0]),
                                        dimension.getDisplayValue(confidenceInterval[1]) }));
                    }

                    align += printBuffer.length();
                    try {
                        while (align++ < 70)
                            printBuffer.append(' ');
                        printBuffer.append(checkSampleSize(s, sample, dimension));
                    }
                    catch (CoreException x) {
                        badDimensions.add(dimension);
                        continue;
                    }

                    ps.print(nameString);
                    ps.print(meanString);
                    ps.println(printBuffer);
                }

                if (!badDimensions.isEmpty()) {
                    ps.print("  Dimensions with unusable statistical properties: "); //$NON-NLS-1$
                    for (Iterator<Dim> iter = badDimensions.iterator(); iter.hasNext();) {
                        Dim dimension = iter.next();
                        ps.print(dimension.getName());
                        if (iter.hasNext())
                            ps.print(", "); //$NON-NLS-1$
                    }
                    ps.println();
                }
            }
        }
        ps.println();
    }

    private String checkSampleSize(StatisticsSession s, Sample sample, Dim dimension) throws CoreException {
        long sampleSize = s.getCount(dimension);
        double stdev = s.getStddev(dimension);
        double mean = s.getAverage(dimension);

        if (stdev == 0)
            return ""; //$NON-NLS-1$

        // measurable effect size
        // sampleSize= 16 * stdev^2 / effect^2
        double effectSize = 4 * Math.sqrt(stdev * stdev / sampleSize);

        double base;
        String baseName;
        if (stdev > Math.abs(mean)) {
            base = stdev;
            baseName = "stdev"; //$NON-NLS-1$
        } else {
            base = Math.abs(mean);
            baseName = "mean"; //$NON-NLS-1$
        }
        double fivePercentEffect = 0.05 * base;
        long requiredSampleSizeForFivePercentEffect = Math.round(16 * stdev * stdev / fivePercentEffect / fivePercentEffect + 0.5);

        // if (requiredSampleSizeForFivePercentEffect > 1000 || Double.isNaN(stdev))
        //			throw new CoreException(new Status(IStatus.OK, "org.eclipse.text.performance", IStatus.OK, "no message", null)); //$NON-NLS-1$ //$NON-NLS-2$

        NumberFormat numberInstance = NumberFormat.getNumberInstance();
        numberInstance.setMaximumFractionDigits(1);
        numberInstance.setMinimumFractionDigits(1);

        String measurableMsg = " Measurable effect: " + dimension.getDisplayValue(effectSize) + " (" + numberInstance.format(effectSize / stdev) + " SDs)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        if (fivePercentEffect < effectSize)
            measurableMsg += " (required sample size for an effect of 5% of " + baseName + ": " + requiredSampleSizeForFivePercentEffect + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

        return measurableMsg;
    }

    private int firstNonDigit(String string) {
        int length = string.length();
        for (int i = 0; i < length; i++)
            if (!Character.isDigit(string.charAt(i)) && string.charAt(i) != '-' && string.charAt(i) != '.')
                return i;
        return length;
    }

    void printSampleCSV(PrintStream ps, Sample sample) {
        final char SEPARATOR = '\t';
        DataPoint[] dataPoints = sample.getDataPoints();
        if (dataPoints.length > 0) {
            Dim[] dimensions = dataPoints[0].getDimensions();
            Arrays.sort(dimensions, new DimensionComparator());
            if (dimensions.length > 0) {
                /* print dimensions */
                for (Dim dimension : dimensions) {
                    ps.print(dimension.getName());
                    ps.print(SEPARATOR);
                }
                ps.println("scenario"); //$NON-NLS-1$

                for (int p = 0; p < dataPoints.length - 1; p += 2) {
                    DataPoint before = dataPoints[p];
                    DataPoint after = dataPoints[p + 1];
                    for (Dim dimension : dimensions) {
                        long valBefore = before.getScalar(dimension).getMagnitude();
                        long valAfter = after.getScalar(dimension).getMagnitude();
                        ps.print(valAfter - valBefore);
                        ps.print(SEPARATOR);
                    }
                    ps.print(sample.getShortname() != null ? sample.getShortname() : sample.getScenarioID());
                    ps.println();
                }

                ps.println();
            }
        }
    }

    public void tagAsSummary(boolean global, String shortName, Dimension[] dims) {
        fSummaryIsGlobal = global;
        fShortName = shortName;
        fSummaryDimensions = dims;
    }

    public void setComment(int commentType, String comment) {
        fCommentType = commentType;
        fComment = comment;
    }
}
