<!--
Copyright (c) 2012 Cameron Adams. All rights reserved.
Copyright (c) 2012 Code Aurora Forum. All rights reserved.
Copyright (C) 2013 Google Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Code Aurora Forum Inc., Google Inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This test is based on code written by Cameron Adams and imported from
  http://themaninblue.com/experiment/AnimationBenchmark/html
-->

<!doctype html>
<head>
<title>Benchmark - Balls Animation using CSS Animations on composited CSS property Transform</title>
<style>
html {
    height: 100%;
}

body {
    width: 100%;
    height: 100%;
    overflow: hidden;
    margin: 0;
    padding: 0;
}

span {
    position: absolute;
    width: 12px;
    height: 12px;
    border-radius: 6px;
}
</style>
<script src="../resources/runner.js"></script>
<script src="resources/framerate.js"></script>
<script>
var stageWidth = 600;
var stageHeight = 600;
var maxParticles = 2500;
var minVelocity = 50;
var maxVelocity = 500;
var particleRadius = 6;
var colors = ["#cc0000", "#ffcc00", "#aaff00", "#0099cc", "#194c99", "#661999"];
var animationDuration = 10;

var particles = [];

window.onload = function () {
    PerfTestRunner.prepareToMeasureValuesAsync({done: onCompletedRun, unit: 'fps'});

    generateStyleElement();

    // Create the particles
    for (var i = 0; i < maxParticles; i++) {
        var particle = new Particle(i);
        particle.start();
        particles.push(particle);
    }

    startTrackingFrameRate();
}

function generateStyleElement() {
    var allParticleKeyframes = '';
    for (var i = 0; i < maxParticles; i++)
        allParticleKeyframes += generateParticleKeyframes(i);
    document.querySelector('#keyframes').innerHTML = allParticleKeyframes;
}

function generateParticleKeyframes(index) {
    var keyframes = '@-webkit-keyframes ' + animationNameForIndex(index) + '{\n';

    var angle = Math.PI * 2 * PerfTestRunner.random();
    var velocity = minVelocity + ((maxVelocity - minVelocity) * PerfTestRunner.random());
    var x = stageWidth / 2 - particleRadius;
    var y = stageHeight / 2 - particleRadius;
    var dx = Math.cos(angle) * velocity;
    var dy = Math.sin(angle) * velocity;

    function detectCollision(lineX, normalX, lineY, normalY) {
        var dtx = Infinity;
        var dty = Infinity;
        if (dx * normalX < 0)
            dtx = (lineX - x) / dx;
        if (dy * normalY < 0)
            dty = (lineY - y) / dy;
        var dt = Math.min(dtx, dty);
        var hitX = (dtx < dty);
        return {
            dt: dt,
            x: hitX ? lineX : x + (dx * dt),
            y: hitX ? y + (dy * dt) : lineY,
            dx: hitX ? -dx : dx,
            dy: hitX ? dy : -dy,
        };
    }

    var t = 0;
    keyframes += generateKeyframe(0, x, y);
    while (t < animationDuration) {
        var collisionA = detectCollision(0, 1, 0, 1);
        var collisionB = detectCollision(stageWidth, -1, stageHeight, -1);
        var collision = collisionA.dt < collisionB.dt ? collisionA : collisionB;
        if (t + collision.dt > animationDuration) {
            var dt = animationDuration - t;
            t = animationDuration;
            x += dx * dt;
            y += dy * dt;
        } else {
            t += collision.dt;
            x = collision.x;
            y = collision.y;
            dx = collision.dx;
            dy = collision.dy;
        }
        keyframes += generateKeyframe(t, x, y);
    }

    keyframes += '}\n';
    return keyframes;
}

function generateKeyframe(t, x, y) {
    return (100 * t / animationDuration) + '% { -webkit-transform: translate(' + x + 'px, ' + y + 'px); }\n';
}

function animationNameForIndex(index) {
    return 'animation-' + index;
}

function Particle(index)
{
    // Create visual element for the particle.
    var domNode = document.createElement('span');
    document.body.appendChild(domNode);

    // Set colour of element.
    domNode.style.position = 'absolute';
    domNode.style.left = '0px';
    domNode.style.top = '0px';
    domNode.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
    domNode.style.webkitAnimationTimingFunction = 'linear';
    domNode.style.webkitAnimationIterationCount = 'infinite';
    domNode.style.webkitAnimationDirection = 'alternate';
    domNode.style.webkitAnimationDuration = animationDuration + 's';

    function start() {
        domNode.style.webkitAnimationName = animationNameForIndex(index);
    }

    function destroy()
    {
        document.body.removeChild(domNode);
    }

    this.start = start;
    this.destroy = destroy;
}

function onCompletedRun() {
    testRunning = false;
    stopTrackingFrameRate();

    for (var i = 0; i < particles.length; i++)
        particles[i].destroy();
    particles = [];
}
</script>
<style id="keyframes"></style>
</head>
</html>
