'use strict';

var hex = require('../../value/types/color/hex.js');
var hsla = require('../../value/types/color/hsla.js');
var hslaToRgba = require('../../value/types/color/hsla-to-rgba.js');
var rgba = require('../../value/types/color/rgba.js');
var immediate = require('./immediate.js');
var number = require('./number.js');
var errors = require('../../../../../../../motion-utils@12.36.0/node_modules/motion-utils/dist/es/errors.js');

// Linear color space blending
// Explained https://www.youtube.com/watch?v=LKnqECcg6Gw
// Demonstrated http://codepen.io/osublake/pen/xGVVaN
const mixLinearColor = (from, to, v) => {
    const fromExpo = from * from;
    const expo = v * (to * to - fromExpo) + fromExpo;
    return expo < 0 ? 0 : Math.sqrt(expo);
};
const colorTypes = [hex.hex, rgba.rgba, hsla.hsla];
const getColorType = (v) => colorTypes.find((type) => type.test(v));
function asRGBA(color) {
    const type = getColorType(color);
    errors.warning(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`, "color-not-animatable");
    if (!Boolean(type))
        return false;
    let model = type.parse(color);
    if (type === hsla.hsla) {
        // TODO Remove this cast - needed since Motion's stricter typing
        model = hslaToRgba.hslaToRgba(model);
    }
    return model;
}
const mixColor = (from, to) => {
    const fromRGBA = asRGBA(from);
    const toRGBA = asRGBA(to);
    if (!fromRGBA || !toRGBA) {
        return immediate.mixImmediate(from, to);
    }
    const blended = { ...fromRGBA };
    return (v) => {
        blended.red = mixLinearColor(fromRGBA.red, toRGBA.red, v);
        blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
        blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
        blended.alpha = number.mixNumber(fromRGBA.alpha, toRGBA.alpha, v);
        return rgba.rgba.transform(blended);
    };
};

exports.mixColor = mixColor;
exports.mixLinearColor = mixLinearColor;
