"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var just_curves_1 = require("./vendor/just-curves");
var CENT = 1.0;
var OBJECT = 'object';
var NUMBER = 'number';
var KEYFRAME_ZERO = 0;
var KEYFRAME_MARGIN = 16.666;
var STRING = 'string';
function percentOfTime(t0, t1, tnow) {
    var span = t1 - t0;
    if (span === 0) {
        return CENT;
    }
    var remaining = t1 - tnow;
    return CENT - remaining / span;
}
function valueAtPercent(v0, v1, pc) {
    var span = v1 - v0;
    var gain = span * pc;
    return v0 + gain;
}
function valueAtTime(v0, v1, t0, t1, tnow) {
    var pc = percentOfTime(t0, t1, tnow);
    return valueAtPercent(v0, v1, pc);
}
function interpolateValue(v0, v1, t0, t1, tnow, curve) {
    var pc = percentOfTime(t0, t1, tnow);
    if (pc > CENT) {
        pc = CENT;
    }
    if (curve) {
        pc = curve(pc);
    }
    return valueAtPercent(v0, v1, pc);
}
function interpolate(now, curve, started, ends, origin, destination) {
    if (Array.isArray(origin) && Array.isArray(destination)) {
        var arrayOutput = [];
        for (var i = 0; i < origin.length; i++) {
            arrayOutput[i] = interpolate(now, curve, started, ends, origin[i], destination[i]);
        }
        return arrayOutput;
    }
    if (origin && typeof origin === OBJECT && destination && typeof destination === OBJECT) {
        var objectOutput = {};
        for (var key in origin) {
            objectOutput[key] = interpolate(now, curve, started, ends, origin[key], destination[key]);
        }
        return objectOutput;
    }
    if (typeof origin === NUMBER && typeof destination === NUMBER) {
        return interpolateValue(origin, destination, started, ends, now, curve);
    }
    return origin;
}
function ascendingSort(a, b) {
    return a - b;
}
function numberize(n) {
    return parseInt(n, 10);
}
function sortedKeyframesCached(keyframeGroup) {
    if (keyframeGroup.__sorted) {
        return keyframeGroup.__sorted;
    }
    var sorted = sortedKeyframes(keyframeGroup);
    keyframeGroup.__sorted = sorted;
    return keyframeGroup.__sorted;
}
function sortedKeyframes(keyframeGroup) {
    var keys = Object.keys(keyframeGroup);
    var sorted = keys.sort(ascendingSort).map(numberize);
    return sorted;
}
function getKeyframesList(keyframeGroup, nowValue) {
    var sorted = sortedKeyframesCached(keyframeGroup);
    for (var i = 0; i < sorted.length; i++) {
        var j = i + 1;
        var current = sorted[i];
        var next = sorted[j];
        if (current <= nowValue) {
            if (next > nowValue) {
                return [current, next];
            }
            if (j >= sorted.length) {
                return [current];
            }
        }
    }
}
function calculateValue(keyframeGroup, nowValue) {
    if (!keyframeGroup[KEYFRAME_ZERO]) {
        keyframeGroup[KEYFRAME_ZERO] = {};
    }
    var keyframesList = getKeyframesList(keyframeGroup, nowValue);
    if (!keyframesList || keyframesList.length < 1) {
        return;
    }
    var currentKeyframe = keyframesList[0];
    var currentTransition = keyframeGroup[currentKeyframe];
    var nextKeyframe = keyframesList[1];
    var nextTransition = keyframeGroup[nextKeyframe];
    var finalValue = getTransitionValue(currentKeyframe, currentTransition, nextKeyframe, nextTransition, nowValue);
    return finalValue;
}
function calculateValueAndReturnUndefinedIfNotWorthwhile(keyframeGroup, nowValue) {
    if (!keyframeGroup[KEYFRAME_ZERO]) {
        keyframeGroup[KEYFRAME_ZERO] = {};
    }
    var keyframesList = getKeyframesList(keyframeGroup, nowValue);
    if (!keyframesList || keyframesList.length < 1) {
        return void 0;
    }
    var currentKeyframe = keyframesList[0];
    var nextKeyframe = keyframesList[1];
    var currentTransition = keyframeGroup[currentKeyframe];
    var nextTransition = keyframeGroup[nextKeyframe];
    if ((currentTransition && currentTransition.machine) ||
        (nextTransition && nextTransition.machine)) {
        return getTransitionValue(currentKeyframe, currentTransition, nextKeyframe, nextTransition, nowValue);
    }
    if (nextKeyframe === undefined) {
        if (nowValue <= currentKeyframe + KEYFRAME_MARGIN) {
            return getTransitionValue(currentKeyframe, currentTransition, nextKeyframe, nextTransition, nowValue);
        }
        return void 0;
    }
    if (nowValue <= nextKeyframe + KEYFRAME_MARGIN) {
        return getTransitionValue(currentKeyframe, currentTransition, nextKeyframe, nextTransition, nowValue);
    }
    return void 0;
}
function getTransitionValue(currentKeyframe, currentTransition, nextKeyframe, nextTransition, nowValue) {
    var currentValue = currentTransition.value;
    if (!currentTransition.curve) {
        return currentValue;
    }
    if (!nextTransition) {
        return currentValue;
    }
    var currentCurve = currentTransition.curve;
    if (typeof currentCurve === STRING) {
        currentCurve = just_curves_1.default[currentCurve];
    }
    var nextValue = nextTransition.value;
    var finalValue = interpolate(nowValue, currentCurve, currentKeyframe, nextKeyframe, currentValue, nextValue);
    return finalValue;
}
exports.default = {
    calculateValue: calculateValue,
    calculateValueAndReturnUndefinedIfNotWorthwhile: calculateValueAndReturnUndefinedIfNotWorthwhile,
    sortedKeyframes: sortedKeyframes,
};
//# sourceMappingURL=Transitions.js.map