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

const FlowScene = (function () {
    const COLORS = [
        {r: 0, g: 0, b: 255},
        {r: 0, g: 64, b: 255},
        {r: 0, g: 128, b: 255},
        {r: 0, g: 192, b: 255}
    ];
    const DISTANCE = 5;

    const SPEED = 30;
    const DIRECTION = 1;

    function getName() {
        return "Flow";
    }

    function getIdentifier() {
        return "com.corsair.cc.sc.flow";
    }

    function getParameters() {
        return [
            {
                name: "color_hint",
                title: "This scene uses pre-defined colors.",
                type: "hint"
            }
        ];
    }

    function moveBubbles(bubbles, distance) {
        bubbles.forEach(function (bubble) {
            bubble.start += distance;
        });
    }

    function randomSize(sizeMax) {
        return sizeMax + Math.floor(sizeMax * (Math.random() - 0.5) / 4.0 * 2);
    }

    function generateScene(sceneID, sceneName, numLeds, ignore) {

        const colors = COLORS.sort(function (a, b) { //jslint-ignore-line
            return 0.5 - Math.random();
        });
        const len = colors.length;
        const sizeMax = Math.floor(parseFloat(numLeds - (len * DISTANCE)) / parseFloat(len));

        let bubbles = [];

        let i = 0;
        let bubbleStart = 0;
        let randSize = randomSize(sizeMax);

        while ((bubbleStart + randSize) < numLeds) {
            bubbles.push({
                size: randSize,
                color: colors[i],
                start: bubbleStart
            });

            i += 1;
            bubbleStart += randSize + DISTANCE;
            randSize = randomSize(sizeMax);
        }

        let sceneData = ScenesCommon.createSceneData(sceneID, numLeds, sceneName);

        if (parseInt(DIRECTION) === 1) {
            for (i = 0; i < numLeds; i += 1) {
                moveBubbles(bubbles, 1);
                addBubblesToSceneData(sceneData, numLeds, bubbles);
            }
        } else {
            for (i = numLeds; i > 0; i -= 1) {
                moveBubbles(bubbles, -1);
                addBubblesToSceneData(sceneData, numLeds, bubbles);
            }
        }

        return sceneData;
    }

    function bubbleAt(led, numLeds, bubbles) {
        return bubbles.find(function (bubble) {

            let start = bubble.start % numLeds;
            let end = (bubble.start + bubble.size) % numLeds;

            if (start < end) {
                return (led >= start) && (led < end);
            }

            return (led >= start) || (led < end);
        });
    }

    function addBubblesToSceneData(sceneData, numLeds, bubbles) {

        let sceneDataSet = ScenesCommon.createSceneDataSet(numLeds, SPEED);
        let led = 0;

        for (led = 0; led < numLeds; led += 1) {
            let bubble = bubbleAt(led, numLeds, bubbles);

            if (bubble !== undefined && bubble.color !== undefined) {
                ScenesCommon.pushColor(sceneDataSet.rgbArray, bubble.color);
            } else {
                ScenesCommon.pushColor(sceneDataSet.rgbArray, ScenesCommon.BLACK_COLOR);
            }
        }

        // Add set
        sceneData.sceneDatas.push(sceneDataSet);
    }

    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="M6.707,9.279c0.001,0.025 0.001,0.05 0.001,0.075c0,1.368 -1.111,2.479 -2.479,2.479c-1.368,0 -2.479,-1.111 -2.479,-2.479c0,-1.368 1.111,-2.479 2.479,-2.479c0.146,-0 0.288,0.013 0.427,0.037c-0.102,-0.342 -0.156,-0.704 -0.156,-1.079c0,-2.092 1.699,-3.791 3.792,-3.791c2.092,-0 3.791,1.699 3.791,3.791c0,2.093 -1.699,3.792 -3.791,3.792c-0.566,-0 -1.103,-0.124 -1.585,-0.346Zm-3.553,0.04c0.099,-0.324 0.378,-0.569 0.721,-0.619c0.273,-0.04 0.462,-0.293 0.423,-0.567c-0.04,-0.273 -0.294,-0.462 -0.567,-0.423c-0.728,0.106 -1.322,0.627 -1.533,1.315c-0.081,0.264 0.067,0.544 0.331,0.625c0.264,0.081 0.544,-0.068 0.625,-0.331Zm3.341,-4.037c0.21,-0.684 0.801,-1.203 1.524,-1.308c0.274,-0.04 0.463,-0.294 0.423,-0.567c-0.039,-0.273 -0.293,-0.462 -0.566,-0.423c-1.11,0.161 -2.015,0.956 -2.337,2.004c-0.081,0.264 0.068,0.544 0.331,0.625c0.264,0.081 0.544,-0.067 0.625,-0.331Zm5.588,4.343c1.196,-0 2.167,0.971 2.167,2.167c0,1.195 -0.971,2.166 -2.167,2.166c-1.195,0 -2.166,-0.971 -2.166,-2.166c-0,-1.196 0.971,-2.167 2.166,-2.167Zm-0.411,2.04c0.048,-0.156 0.183,-0.275 0.349,-0.299c0.273,-0.04 0.462,-0.294 0.423,-0.567c-0.04,-0.273 -0.294,-0.463 -0.567,-0.423c-0.551,0.08 -1.001,0.475 -1.161,0.996c-0.081,0.264 0.067,0.544 0.331,0.625c0.264,0.081 0.544,-0.068 0.625,-0.332Z"/>
</svg>`;
    }

    function getColors() {
        return ScenesCommon.hexColors(COLORS);
    }

    return {
        name: getName,
        identifier: getIdentifier,
        parameters: getParameters,
        generate_scene: generateScene,
        icon: getIcon,
        colors: getColors
    };
}());


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

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

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

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

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

function getColors() {
    return FlowScene.colors();
}
