/*******************************************************************************
 * Copyright (c) 2000, 2009 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.results.db;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.StringTokenizer;

import org.eclipse.test.internal.performance.InternalPerformanceMeter;
import org.eclipse.test.internal.performance.PerformanceTestPlugin;
import org.eclipse.test.internal.performance.data.Dim;
import org.eclipse.test.internal.performance.results.utils.Util;

/**
 * Class providing numbers of a scenario running on a specific configuration
 * at a specific time (for example 'I20070615-1200').
 */
public class BuildResults extends AbstractResults {

    private static final double IMPOSSIBLE_VALUE = -1E6;

    // Build information
    String                      date;
    String                      comment;
    int                         summaryKind      = -1;

    // Dimensions information
    Dim[]                       dimensions;
    double[]                    average, stddev;
    long[]                      count;
    double[][]                  values;
    boolean                     hadValues        = false;
    private int                 defaultDimIndex  = -1;

    // Comparison information
    boolean                     baseline;
    String                      failure;

    BuildResults(AbstractResults parent) {
        super(parent, -1);
    }

    BuildResults(AbstractResults parent, int id) {
        super(parent, id);
        this.name = DB_Results.getBuildName(id);
        this.baseline = this.name.startsWith(DB_Results.getDbBaselinePrefix());
    }

    /*
     * Clean values when several measures has been done for the same build.
     */
    void cleanValues() {
        int length = this.values.length;
        for (int dim_id = 0; dim_id < length; dim_id++) {
            int vLength = this.values[dim_id].length;
		/* Log clean operation
		if (dim_id == 0) {
			IStatus status = new Status(IStatus.WARNING, PerformanceTestPlugin.PLUGIN_ID, "Clean "+vLength+" values for "+this.parent+">"+this.name+" ("+this.count[dim_id]+" measures)...");    //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$ //$NON-NLS-5$
			PerformanceTestPlugin.log(status);
		}
             */
            this.average[dim_id] = 0;
            for (int i = 0; i < vLength; i++) {
                this.average[dim_id] += this.values[dim_id][i];
            }
            this.average[dim_id] /= vLength;
            double squaredDeviations = 0;
            for (int i = 0; i < vLength; i++) {
                double deviation = this.average[dim_id] - this.values[dim_id][i];
                squaredDeviations += deviation * deviation;
            }
		this.stddev[dim_id] = Math.sqrt(squaredDeviations / (this.count[dim_id] - 1)); // unbiased sample stdev
            this.values[dim_id] = null;
        }
        for (int i = 0; i < length; i++) {
            if (this.values[i] != null) {
                return;
            }
        }
        this.values = null;
        this.hadValues = true;
    }

    /**
     * Compare build results using the date of the build.
     *
     * @see Comparable#compareTo(Object)
     */
    public int compareTo(Object obj) {
        if (obj instanceof BuildResults) {
            BuildResults res = (BuildResults) obj;
            return getDate().compareTo(res.getDate());
        }
        return -1;
    }

    /**
     * Returns the most recent baseline build results.
     *
     * @return The {@link BuildResults baseline build results}.
     * @see BuildResults
     */
    public BuildResults getBaselineBuildResults() {
        return ((ConfigResults) this.parent).getBaselineBuildResults();
    }

    /**
     * Returns the comment associated with the scenario for the current build.
     *
 * @return The comment associated with the scenario for the current build
 * 	or <code>null</code> if no comment was stored for it.
     */
    public String getComment() {
        return this.comment;
    }

    /**
     * Return the number of stored values for the default dimension
     *
     * @return the number of stored values for the default dimension
     */
    public long getCount() {
        if (this.defaultDimIndex < 0) {
            this.defaultDimIndex = DB_Results.getDefaultDimensionIndex();
        }
        return this.count[this.defaultDimIndex];
    }

    /**
     * Return the number of stored values for the given dimension.
     *
 * @param dim_id The id of the dimension (see {@link Dim#getId()})
     * @return the number of stored values for the given dimension
     *
     */
    public long getCount(int dim_id) {
        return this.count[getDimIndex(dim_id)];
    }

    /**
     * Returns the date of the build which is a part of its name.
     *
     * @return The date of the build as yyyyMMddHHmm
     */
    public String getDate() {
        if (this.date == null) {
            if (this.baseline) {
                int length = this.name.length();
                this.date = this.name.substring(length - 12, length);
            } else {
                char first = this.name.charAt(0);
			if (first == 'N' || first == 'I' || first == 'M') { // TODO (frederic) should be buildIdPrefixes...
                    if (this.name.length() == 14) {
                        this.date = this.name.substring(1, 9) + this.name.substring(10, 14);
                    } else {
                        this.date = this.name.substring(1);
                    }
                } else {
                    int length = this.name.length() - 12 /* length of date */;
                    for (int i = 0; i <= length; i++) {
                        try {
                            String substring = i == 0 ? this.name : this.name.substring(i);
                            Util.DATE_FORMAT.parse(substring);
						this.date = substring; // if no exception is raised then the substring has a correct date format => store it
                            break;
					} catch(ParseException ex) {
                            // skip
                        }
                    }
                }
            }
        }
        return this.date;
    }

    /**
 * Returns the standard deviation of the default dimension computed
 * while running the scenario for the current build.
     *
     * @return The value of the standard deviation
     */
    public double getDeviation() {
        if (this.defaultDimIndex < 0) {
            this.defaultDimIndex = DB_Results.getDefaultDimensionIndex();
        }
        return this.stddev[this.defaultDimIndex];
    }

    /**
 * Returns the standard deviation of the given dimension computed
 * while running the scenario for the current build.
     *
 * @param dim_id The id of the dimension (see {@link Dim#getId()})
     * @return The value of the standard deviation
     */
    public double getDeviation(int dim_id) {
        final int dimIndex = getDimIndex(dim_id);
        return dimIndex < 0 ? 0 : this.stddev[dimIndex];
    }

    /**
     * Returns the dimensions supported for the current build.
     *
     * @return An array of dimensions.
     */
    public Dim[] getDimensions() {
        return this.dimensions;
    }

    /**
     * Returns the kind of summary for the scenario of the current build.
     *
 * @return -1 if the scenario has no summary, 1 if it's a global summary, 0 otherwise.
     */
    public int getSummaryKind() {
        return this.summaryKind;
    }

    /**
     * Returns whether the current build had several values stored in database.
     *
     * @return <code>true</code> if the measure was committed several times,
     *         <code>false</code> otherwise.
     */
    public boolean hadValues() {
        return this.hadValues;
    }

    /*
 * Return the index of the dimension corresponding to the given
 * dimension id (see {@link Dim#getId()})
     */
    int getDimIndex(int dim_id) {
	if (this.dimensions == null) return -1;
        int length = this.dimensions.length;
        for (int i = 0; i < length; i++) {
		if (this.dimensions[i] == null) break;
            if (this.dimensions[i].getId() == dim_id) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Return the error computed while storing values for the default dimension
     *
     * @return the error of the measures stored for the default dimension
     */
    public double getError() {
        long n = getCount();
	if (n == 1) return Double.NaN;
        return getDeviation() / Math.sqrt(n);
    }

    /**
     * Return the error computed while storing values for the given dimension.
     *
 * @param dim_id The id of the dimension (see {@link Dim#getId()})
     * @return the error of the measures stored for the given dimension
     */
    public double getError(int dim_id) {
        long n = getCount(dim_id);
	if (n == 1) return Double.NaN;
        return getDeviation(dim_id) / Math.sqrt(n);
    }

    /**
 * Return the failure message which may happened on this scenario
 * while running the current build
     *
     * @return The failure message or <code>null</null> if the scenario passed.
     */
    public String getFailure() {
        return this.failure;
    }

    /**
 * Return the value of the performance result stored
 * for the given dimension of the current build.
     *
 * @param dim_id The id of the dimension (see {@link Dim#getId()})
     * @return The value of the performance result
     */
    public double getValue(int dim_id) {
        int idx = getDimIndex(dim_id);
	if (idx < 0) return Double.NaN;
        return this.average[idx];
    }

    /**
 * Return the value of the performance result stored
 * for the default dimension of the current build.
     *
     * @return The value of the performance result
     */
    public double getValue() {
        if (this.defaultDimIndex < 0) {
            this.defaultDimIndex = DB_Results.getDefaultDimensionIndex();
        }
        return this.average[this.defaultDimIndex];
    }

    /**
     * Returns whether the build is a baseline build or not.
     *
 * @return <code>true</code> if the build name starts with the baseline prefix
 * 	(see {@link PerformanceResults#getBaselinePrefix()} or <code>false</code>
 * 	otherwise.
     */
    public boolean isBaseline() {
        return this.baseline;
    }

    /**
 * Returns whether the build has a summary or not. Note that the summary
 * may be global or not.
     *
     * @return <code>true</code> if the summary kind is equals to 0 or 1
     *         <code>false</code> otherwise.
     */
    public boolean hasSummary() {
        return this.summaryKind >= 0;
    }

    /**
     * Returns whether the build has a global summary or not.
     *
     * @return <code>true</code> if the summary kind is equals to 1
     *         <code>false</code> otherwise.
     */
    public boolean hasGlobalSummary() {
        return this.summaryKind == 1;
    }

    /*
     * Returns a given pattern match the build name or not.
     */
    boolean match(String pattern) {
	if (pattern.equals("*")) return true; //$NON-NLS-1$
        if (pattern.indexOf('*') < 0 && pattern.indexOf('?') < 0) {
            pattern += "*"; //$NON-NLS-1$
        }
        StringTokenizer tokenizer = new StringTokenizer(pattern, "*?", true); //$NON-NLS-1$
        int start = 0;
        String previous = ""; //$NON-NLS-1$
        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            if (!token.equals("*") && !token.equals("?")) { //$NON-NLS-1$ //$NON-NLS-2$
                if (previous.equals("*")) { //$NON-NLS-1$
                    int idx = this.name.substring(start).indexOf(token);
				if (idx < 0) return false;
                    start += idx;
                } else {
				if (previous.equals("?")) start++; //$NON-NLS-1$
				if (!this.name.substring(start).startsWith(token)) return false;
                }
                start += token.length();
            }
            previous = token;
        }
        if (previous.equals("*")) { //$NON-NLS-1$
            return true;
        } else if (previous.equals("?")) { //$NON-NLS-1$
            return this.name.length() == start;
        }
        return this.name.endsWith(previous);
    }

    /*
     * Read the build results data from the given stream.
     */
    void readData(DataInputStream stream) throws IOException {
        long timeBuild = stream.readLong();
        this.date = new Long(timeBuild).toString();
        byte kind = stream.readByte();
        this.baseline = kind == 0;
        if (this.baseline) {
		this.name = getPerformance().baselinePrefix + '-' + this.date;
        } else {
            String suffix = this.date.substring(0, 8) + '-' + this.date.substring(8);
            switch (kind) {
                case 1:
                    this.name = "N" + suffix; //$NON-NLS-1$
                    break;
                case 2:
                    this.name = "I" + suffix; //$NON-NLS-1$
                    break;
                case 3:
                    this.name = "M" + suffix; //$NON-NLS-1$
                    break;
                default:
                    this.name = stream.readUTF();
                    break;
            }
        }
        int length = stream.readInt();
        this.dimensions = new Dim[length];
        this.average = new double[length];
        this.stddev = new double[length];
        this.count = new long[length];
        for (int i = 0; i < length; i++) {
            int dimId = stream.readInt();
            DB_Results.storeDimension(dimId);
            this.dimensions[i] = (Dim) PerformanceTestPlugin.getDimension(dimId);
            this.average[i] = stream.readLong();
            this.count[i] = stream.readLong();
            this.stddev[i] = stream.readDouble();
        }
        this.id = DB_Results.getBuildId(this.name);

        // read summary
        this.summaryKind = stream.readInt();

        // read comment
        String str = stream.readUTF();
        if (str.length() > 0) {
            this.comment = str;
        }
    }

    /*
     * Set the build summary and its associated comment.
     */
    void setComment(String comment) {
        if (comment != null && this.comment == null) {
            this.comment = comment;
        }
    }

    /*
     * Set the build summary and its associated comment.
     */
    void setSummary(int kind, String comment) {
        this.comment = comment;
        this.summaryKind = kind;
    }

    /*
     * Set the build failure.
     */
    void setFailure(String failure) {
        this.failure = failure;
    }

    /*
     * Set the build value from database information.
     */
    void setValue(int dim_id, int step, long value) {
        int length = DB_Results.getDimensions().length;
        Dim dimension = (Dim) PerformanceTestPlugin.getDimension(dim_id);
        int idx = 0;
        if (this.dimensions == null) {
            this.dimensions = new Dim[length];
            this.average = new double[length];
            this.stddev = new double[length];
            this.count = new long[length];
            this.dimensions[0] = dimension;
            for (int i = 0; i < length; i++) {
                // init average numbers with an impossible value
                // to clearly identify whether it's already set or not
                // when several measures are made for the same build
                this.average[i] = IMPOSSIBLE_VALUE;
            }
        } else {
            length = this.dimensions.length;
            for (int i = 0; i < length; i++) {
                if (this.dimensions[i] == null) {
                    this.dimensions[i] = dimension;
                    idx = i;
                    break;
                }
                if (this.dimensions[i].getId() == dim_id) {
                    idx = i;
                    break;
                }
            }
        }
        switch (step) {
            case InternalPerformanceMeter.AVERAGE:
                if (this.average[idx] != IMPOSSIBLE_VALUE) {
                    if (this.values == null) {
                        this.values = new double[length][];
                        this.values[idx] = new double[2];
                        this.values[idx][0] = this.average[idx];
                        this.values[idx][1] = value;
                        this.average[idx] = IMPOSSIBLE_VALUE;
                    } else if (this.values[idx] == null) {
                        this.values[idx] = new double[2];
                        this.values[idx][0] = this.average[idx];
                        this.values[idx][1] = value;
                        this.average[idx] = IMPOSSIBLE_VALUE;
                    }
                } else if (this.values != null && this.values[idx] != null) {
                    int vLength = this.values[idx].length;
                    System.arraycopy(this.values[idx], 0, this.values[idx] = new double[vLength + 1], 0, vLength);
                    this.values[idx][vLength] = value;
                } else {
                    this.average[idx] = value;
                }
                break;
            case InternalPerformanceMeter.STDEV:
                this.stddev[idx] += Double.longBitsToDouble(value);
                break;
            case InternalPerformanceMeter.SIZE:
                this.count[idx] += value;
                break;
        }
    }

/* (non-Javadoc)
 * @see org.eclipse.test.internal.performance.results.AbstractResults#toString()
     */
    public String toString() {
        StringBuffer buffer = new StringBuffer(this.name);
        buffer.append(": "); //$NON-NLS-1$
        int length = this.dimensions.length;
        for (int i = 0; i < length; i++) {
		if (i>0)	buffer.append(", "); //$NON-NLS-1$
            buffer.append('[');
            buffer.append(this.dimensions[i].getId());
            buffer.append("]="); //$NON-NLS-1$
            buffer.append(this.average[i]);
            buffer.append('/');
            buffer.append(this.count[i]);
            buffer.append('/');
            buffer.append(Math.round(this.stddev[i] * 1000) / 1000.0);
        }
        return buffer.toString();
    }

    /*
     * Write the build results data in the given stream.
     */
    void write(DataOutputStream stream) throws IOException {
        if (DO_NOT_WRITE_DATA) {
            return;
        }
        boolean okToWrite = true;
        long timeBuild = -1;
        String dateFound = null;
        try {
            dateFound = getDate();
            timeBuild = Long.parseLong(dateFound);
        }
        catch (NumberFormatException nfe) {
            // do nothing, but do not write bad data.
            // nfe.printStackTrace();
            System.out.println("ERROR: Found number format exception converting date. Date: >"+ dateFound +"<." + "Could be corrupt data in DB?");
            okToWrite = false;
        }
        if (okToWrite) {
            stream.writeLong(timeBuild);
            byte kind = 0; // baseline
            if (!this.baseline) {
                switch (this.name.charAt(0)) {
                    case 'N':
                        kind = 1;
                        break;
                    case 'I':
                        kind = 2;
                        break;
                    case 'M':
                        kind = 3;
                        break;
                    default:
                        kind = 4;
                        break;
                }
            }
            stream.writeByte(kind);
            if (kind == 4) {
                stream.writeUTF(this.name);
            }
            int length = this.dimensions == null ? 0 : this.dimensions.length;
            stream.writeInt(length);
            for (int i = 0; i < length; i++) {
                stream.writeInt(this.dimensions[i].getId());
                stream.writeLong((long) this.average[i]);
                stream.writeLong(this.count[i]);
                stream.writeDouble(this.stddev[i]);
            }

            // Write extra infos (summary, failure and comment)
            stream.writeInt(this.summaryKind);
            stream.writeUTF(this.comment == null ? "" : this.comment); //$NON-NLS-1$
        }
    }

}
