/*jslint single: true, long:true, for:true, unordered:true*/
/*global ScenesCommon*/

const SirenScene = (function ()
{
    const MIN_PULSE_WIDTH = 10;
    const MAX_PULSE_WIDTH = 100;
    
    function getName()
    {
        return "Siren";
    }
    function getIdentifier()
    {
        return "com.corsair.cc.sc.siren";
    }
    function getParameters()
    {
        return [
            {
                name: "color_hint",
                title: "Define up to 7 colors for your scene.",
                type: "hint"
            },
			{
				name: "colors",
				title: "Colors",
				type: "color_list",
				min: 2,
				max: 6,
				default: ["#ff0000", "#0000ff", "#ff0000", "#0000ff"]
			},
            {
                name: "background",
                title: "Background",
                type: "color",
                default: "#ffffff"
            },
            {
                name: "pulseWidth",
                title: "Pulse Width",
                type: "int",              
				min: MIN_PULSE_WIDTH,
				max: MAX_PULSE_WIDTH,
                default: 60
            },
            {
                name: "speed",
                title: "Speed",
                type: "int_enum",
/*jslint-disable*/
                values: {300: "Very Slow", 50: "Slow", 20: "Medium", 3: "Fast"},
/*jslint-enable*/
                default: 20
            },
			{
				name: "direction",
                title: "Direction",
                type: "int_enum",
/*jslint-disable*/
                values: {0: "Forward", 1: "Backwards"},
/*jslint-enable*/
                default: 0
			}
        ];
    }
    
    function clampColor(number) {
        const min = 0;
        const max = 255;
        return Math.max(min, Math.min(number, max));
    }
    
    function mix(cOne, cTwo, x)
    {
        var res = {r: 0, g: 0, b: 0};
        var subX = (MAX_PULSE_WIDTH - x) / MAX_PULSE_WIDTH;
        var ratX = x / MAX_PULSE_WIDTH;
        res.r = clampColor(Math.round(cOne.r * subX + cTwo.r * ratX));
        res.g = clampColor(Math.round(cOne.g * subX + cTwo.g * ratX));
        res.b = clampColor(Math.round(cOne.b * subX + cTwo.b * ratX));
        return res;
    }
    
	function generateScene(sceneID, sceneName, numLeds, parameters)
	{
        let sceneData = ScenesCommon.createSceneData(sceneID, numLeds, sceneName);
        const config = getParameters();
		const parameterColors = ScenesCommon.valueOrDefaultFromParameters(parameters, config, "colors");
		const backColor = ScenesCommon.colorFromHexString(ScenesCommon.valueOrDefaultFromParameters(parameters, config, "background"));
		const duration = ScenesCommon.valueOrDefaultFromParameters(parameters, config, "speed");
		const direction = ScenesCommon.valueOrDefaultFromParameters(parameters, config, "direction");
		const pulseWidth = ScenesCommon.valueOrDefaultFromParameters(parameters, config, "pulseWidth");
        
		const numColors = parameterColors.length;
        const selectedColors = parameterColors.map(c => ScenesCommon.colorFromHexString(c));
        
		// Prepare background
        let sceneColors = Array(numLeds).fill().map(item => backColor);
        
        const ledsPerColor = Math.floor(numLeds / numColors);
        for (let i = 0; i < numColors; i++)
        {
            // Set color to the center of the available space
            const colorCenterPos = Math.floor((ledsPerColor * i) + (ledsPerColor / 2));
            sceneColors[colorCenterPos] = selectedColors[i];
            
            // Set decaying color left and right to it
            for (let j = 1; j < ledsPerColor / 2; j++)
            {
                const currentPulseFactor = ((MAX_PULSE_WIDTH - pulseWidth) * j) / (ledsPerColor / 6);
                const mixedColor = mix(selectedColors[i], backColor, currentPulseFactor);
                sceneColors[colorCenterPos + j] = mixedColor;
                sceneColors[colorCenterPos - j] = mixedColor;
            }
        }
        
		// Create multiple sets for animation
        for (let i = 0; i < numLeds; i++)
		{
			let sceneDataSet = ScenesCommon.createSceneDataSet(numLeds, duration);
            for (let i = 0; i < numLeds; i++)
                ScenesCommon.pushColor(sceneDataSet.rgbArray, sceneColors[i]);
            sceneData.sceneDatas.push(sceneDataSet);
        
			// Shift one to the right/left
			if (direction > 0)
                sceneColors.push(sceneColors.shift());
			else
                sceneColors.unshift(sceneColors.pop());
		}
        
        return sceneData;
    }
        
    function getIcon()
	{
        return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 16 16">
	<path id="icon" fill="#d8d8d8" fill-rule="evenodd" d="M2.853,8.434c-0.024,-0.004 -0.048,-0.009 -0.073,-0.015l-1.449,-0.389c-0.399,-0.107 -0.637,-0.518 -0.53,-0.918c0.107,-0.4 0.519,-0.638 0.919,-0.531l1.449,0.389c0.066,0.017 0.127,0.043 0.184,0.076c-0.229,0.431 -0.399,0.897 -0.5,1.388Zm2.208,-3.29c-0.032,-0.036 -0.061,-0.076 -0.086,-0.119l-0.75,-1.3c-0.206,-0.358 -0.083,-0.817 0.275,-1.024c0.358,-0.207 0.818,-0.084 1.025,0.274l0.75,1.3c0.042,0.073 0.071,0.152 0.086,0.231c-0.465,0.153 -0.902,0.369 -1.3,0.638Zm4.578,-0.638c0.015,-0.079 0.044,-0.158 0.086,-0.231l0.75,-1.3c0.207,-0.358 0.667,-0.481 1.025,-0.274c0.358,0.207 0.481,0.666 0.275,1.024l-0.75,1.3c-0.025,0.043 -0.054,0.083 -0.086,0.119c-0.398,-0.269 -0.835,-0.485 -1.3,-0.638Zm3.008,2.54c0.057,-0.033 0.118,-0.059 0.184,-0.076l1.449,-0.389c0.4,-0.107 0.812,0.131 0.919,0.531c0.107,0.4 -0.131,0.811 -0.53,0.918l-1.449,0.389c-0.025,0.006 -0.049,0.011 -0.073,0.015c-0.101,-0.491 -0.271,-0.957 -0.5,-1.388Zm-1.647,4.954l0.25,0c0.414,0 0.75,0.336 0.75,0.75c-0,0.414 -0.336,0.75 -0.75,0.75l-6.5,0c-0.414,0 -0.75,-0.336 -0.75,-0.75c0,-0.414 0.336,-0.75 0.75,-0.75l0.25,0l-0,-2.5c-0,-1.656 1.344,-3 3,-3c1.656,0 3,1.344 3,3l0,2.5Zm-1,0l-0,-2c-0,-1.209 -0.859,-2.218 -2,-2.45l-0,4.45l2,0Z"/>
</svg>`;
    }
    
    function parametersForAIColors(parameters, colors, dynamism) {
        const config = getParameters();
        const speed = ScenesCommon.valueOrDefaultFromParameters(parameters, config, "speed");
        const direction = ScenesCommon.valueOrDefaultFromParameters(parameters, config, "direction");

        let result = {
            "colors": [],
            "speed": speed,
            "direction": direction
        };

        if (colors === null) {
            colors = ScenesCommon.generateAIColorFromParameters(parameters, config);
        } else {
            colors = ScenesCommon.alterArrayForMinMaxParameterName(colors, config, "colors");
        }

        colors.forEach(function (color) {
            result.colors.push(color.colorString);
        });

        if (dynamism !== null) {
            let dynamismFloat = parseFloat(dynamism);

            if (dynamismFloat < ScenesCommon.DYNAMISM_SLOW) { // Slow
                result.speed = 50;
            } else if (dynamismFloat < ScenesCommon.DYNAMISM_MEDIUM) { // Medium
                result.speed = 20;
            } else if (dynamismFloat < ScenesCommon.DYNAMISM_FAST) { // Fast
                result.speed = 3;
            } else { // Fast, too
                result.speed = 3;
            }
        }

        return result;
    }
    
    return {
        name: getName,
        identifier: getIdentifier,
        parameters: getParameters,
        generate_scene: generateScene,
        icon: getIcon,
        "parametersForAIColors": parametersForAIColors
    };
}());

function getName() {
    return SirenScene.name();
}

function getIdentifier() {
    return SirenScene.identifier();
}

function getParameters() {
    return SirenScene.parameters();
}

function generateScene(sceneID, sceneName, numLeds, parameters) {
    return SirenScene.generate_scene(sceneID, sceneName, numLeds, parameters);
}

function getIcon() {
    return SirenScene.icon();
}

function parametersForAIColors(parameters, colors, dynamism) {
    return SirenScene.parametersForAIColors(parameters, colors, dynamism);
}