'use strict';

class Metric extends LabeledObject {
    constructor(id, object)
    {
        super(id, object);
        this._aggregatorName = object.aggregator;
        object.test.addMetric(this);
        this._test = object.test;
        this._platforms = [];

        const suffix = this.name().match('([A-z][a-z]+|FrameRate)$')[0];
        this._unit = {
            'FrameRate': 'fps',
            'Runs': '/s',
            'Time': 'ms',
            'Duration': 'ms',
            'Malloc': 'B',
            'Heap': 'B',
            'Allocations': 'B',
            'Size': 'B',
            'Score': 'pt',
        }[suffix];
    }

    aggregatorName() { return this._aggregatorName; }

    test() { return this._test; }
    platforms() { return this._platforms; }

    addPlatform(platform)
    {
        console.assert(platform instanceof Platform);
        this._platforms.push(platform);
    }

    childMetrics()
    {
        var metrics = [];
        for (var childTest of this._test.childTests()) {
            for (var childMetric of childTest.metrics())
                metrics.push(childMetric);
        }
        return metrics;
    }

    path() { return this._test.path().concat([this]); }

    fullName() { return this._test.fullName() + ' : ' + this.label(); }

    relativeName(path)
    {
        const relativeTestName = this._test.relativeName(path);
        if (relativeTestName == null)
            return this.label();
        return relativeTestName + ' : ' + this.label();
    }

    aggregatorLabel()
    {
        switch (this._aggregatorName) {
        case 'Arithmetic':
            return 'Arithmetic mean';
        case 'Geometric':
            return 'Geometric mean';
        case 'Harmonic':
            return 'Harmonic mean';
        case 'Total':
            return 'Total';
        }
        return null;
    }

    label()
    {
        const aggregatorLabel = this.aggregatorLabel();
        return this.name() + (aggregatorLabel ? ` : ${aggregatorLabel}` : '');
    }

    unit() { return this._unit; }

    isSmallerBetter()
    {
        const unit = this._unit;
        return unit != 'fps' && unit != '/s' && unit != 'pt';
    }

    labelForDifference(beforeValue, afterValue, progressionTypeName, regressionTypeName)
    {
        const diff = afterValue - beforeValue;
        const changeType = diff < 0 == this.isSmallerBetter() ? progressionTypeName : regressionTypeName;
        const relativeChange = diff / beforeValue * 100;
        const changeLabel = Math.abs(relativeChange).toFixed(2) + '% ' + changeType;
        return {changeType, relativeChange, changeLabel};
    }

    makeFormatter(sigFig, alwaysShowSign) { return Metric.makeFormatter(this.unit(), sigFig, alwaysShowSign); }

    static makeFormatter(unit, sigFig = 2, alwaysShowSign = false)
    {
        let isMiliseconds = false;
        if (unit == 'ms') {
            isMiliseconds = true;
            unit = 's';
        }

        if (!unit)
            return function (value) { return value.toFixed(2) + ' ' + (unit || ''); }

        var divisor = unit == 'B' ? 1024 : 1000;
        var suffix = ['\u03BC', 'm', '', 'K', 'M', 'G', 'T', 'P', 'E'];
        var threshold = sigFig >= 3 ? divisor : (divisor / 10);
        let formatter = function (value, maxAbsValue = 0) {
            var i;
            var sign = value >= 0 ? (alwaysShowSign ? '+' : '') : '-';
            value = Math.abs(value);
            let sigFigForValue = sigFig;

            // The number of sig-figs to reduce in order to match that of maxAbsValue
            // e.g. 0.5 instead of 0.50 when maxAbsValue is 2.
            let adjustment = 0;
            if (maxAbsValue && value)
                adjustment = Math.max(0, Math.floor(Math.log(maxAbsValue) / Math.log(10)) - Math.floor(Math.log(value) / Math.log(10)));

            for (i = isMiliseconds ? 1 : 2; value && value < 1 && i > 0; i--)
                value *= divisor;
            for (; value >= threshold; i++)
                value /= divisor;

            if (adjustment) // Make the adjustment only for decimal positions below 1.
                adjustment = Math.min(adjustment, Math.max(0, -Math.floor(Math.log(value) / Math.log(10))));

            return sign + value.toPrecision(sigFig - adjustment) + ' ' + suffix[i] + (unit || '');
        }
        formatter.divisor = divisor;
        return formatter;
    };

    static formatTime(utcTime)
    {
        // FIXME: This is incorrect when the offset cross day-life-saving change. It's good enough for now.
        const offsetInMinutes = (new Date(utcTime)).getTimezoneOffset();
        const timeInLocalTimeZone = new Date(utcTime - offsetInMinutes * 60 * 1000);
        return timeInLocalTimeZone.toISOString().replace('T', ' ').replace(/\.\d+Z$/, '');
    }
}

if (typeof module != 'undefined')
    module.exports.Metric = Metric;
