var p;
var t;
var r;
var _imageData   = new Array();
var _point       = new Array();
var _pointImage  = new Array();

var _playgroundWidth   = 0.2 * screen.width;
var _playgroundHeight  = screen.height;

var _constantDiffH     = 100;
var _constantDiffV     = 100;
var _variableDiffH     = 50;
var _variableDiffV     = 100;
var _controlRadius     = 100;
var _interpolation     = 100;
var _refreshTime       = 100;
var _rotation          = true;
var _breaks            = true;
var _rotationAfterStop = true;
var _colorChange       = true;
var _collisionStop     = true;
var _fadeIn            = true;
var _imagePath         = "";
var _numOfAnimations   = 4;

function getParams() {
  e = document.getElementById("animation_param_numOfAnimations");
  if (e != null) _numOfAnimations = e.value;
  e = document.getElementById("animation_param_playgfieldWidth");
  if (e != null) _playgroundWidth = (parseFloat(e.value) / 100.0) * screen.width;
  e = document.getElementById("animation_param_playfieldHeight");
  if (e != null) _playgroundHeight =(parseFloat(e.value) / 100.0) * screen.height;
  e = document.getElementById("animation_param_refreshTime");
  if (e != null) _refreshTime = e.value;
  e = document.getElementById("animation_param_interpolation_steps");
  if (e != null) _interpolation = e.value;
  e = document.getElementById("animation_param_constantDiffH");
  if (e != null) _constantDiffH = e.value;
  e = document.getElementById("animation_param_constantDiffV");
  if (e != null) _constantDiffV = e.value;
  e = document.getElementById("animation_param_variableDiffH");
  if (e != null) _variableDiffH = e.value;
  e = document.getElementById("animation_param_variableDiffV");
  if (e != null) _variableDiffV = e.value;
  e = document.getElementById("animation_param_controlRadius");
  if (e != null) _controlRadius = e.value;
  
  e = document.getElementById("animation_param_rotation");
  if (e != null) _rotation = e.value == 1;
  e = document.getElementById("animation_param_breaks");
  if (e != null) _breaks = e.value == 1;
  e = document.getElementById("animation_param_rotationAfterStop");
  if (e != null) _rotationAfterStop = e.value == 1;
  e = document.getElementById("animation_param_colorChange");
  if (e != null) _colorChange = e.value == 1;
  e = document.getElementById("animation_param_collisionStop");
  if (e != null) _collisionStop = e.value == 1;
  e = document.getElementById("animation_param_fadeIn");
  if (e != null) _fadeIn = e.value == 1;
}

function start(imagePath) {
  _imagePath = imagePath;
  init(true);
}

function init(start) {

  getParams();

  playground = document.getElementById("playGround");
  for (i = 0; i < _numOfAnimations; i++) {
    playground.innerHTML += "<div id='point_" + i + "' style='position:absolute;top:" + (80 + i * 30) + "px;left:80px;opacity:0.0;filter:alpha(opacity = 0);'><a href='#' onClick='javascript:pause(" + i + ");return false;'><img id='point_" + i + "_image' src='" + _imagePath + "/red_points_0.gif' border='0' /></a></div>";
  }
  
  _imageData = new Array();
  for (i = 0; i < 9; i++) {
    _imageData[i] = new Image();
    _imageData[i].src = _imagePath + "/red_points_" + (i * 10) + ".gif";
  }
  for (i = 0; i < 9; i++) {
    _imageData[i + 10] = new Image();
    _imageData[i + 10].src = _imagePath + "/green_points_" + (i * 10) + ".gif";
  }
  
  width     = 25;
  startX    = new Array();
  startY    = new Array();
  endX      = new Array();
  endY      = new Array();
  control1X = new Array();
  control1Y = new Array();
  control2X = new Array();
  control2Y = new Array();
  x         = new Array();
  y         = new Array();
  p         = new Array();
  
  for (i = _numOfAnimations; i-- > 0;) {
    
    forceX     = .02;
    directionX = ((Math.random() < 0.5) ? -1 : 1);
    directionY = ((Math.random() < 0.5) ? -1 : 1);
    
    // interpolation points
    startX[i]    = Math.random() * _playgroundWidth;//Math.floor(i * width);
    startY[i]    = Math.random() * (screen.height - 300);//125;
    endX[i]      = startX[i] + ((Math.random() * _variableDiffH) + _constantDiffH) * directionX;
    endY[i]      = startY[i] + ((Math.random() * _variableDiffV) + _constantDiffV) * directionY;
    control1X[i] = startX[i];
    control1Y[i] = endY[i];
    control2X[i] = endX[i] + _controlRadius * Math.cos(Math.random());
    control2Y[i] = endY[i] + _controlRadius * Math.sin(Math.random());
    x[i]         = startX[i];
    y[i]         = startY[i];
    
    p[i] = new Array( new Array( startX[i], startY[i] ),
                      new Array( control1X[i], control1Y[i] ),
                      new Array( control2X[i], control2Y[i] ),
                      new Array( endX[i], endY[i] ),
                      new Array( forceX, _interpolation, directionX, directionY, 0, 0, 0, 0 ),
                      new Array( x[i], y[i] ) );
                      
  }
                   
  t = 0.0;
  rot = 0;
  
  if (start) window.setTimeout('animate();', 0);
}

function pause(i) {
  if (_breaks) p[i][4][5] = (p[i][4][5] + 1) % 2;
}

function newPathSegment(i, rand) {
  // y = mx + b
  m = (p[i][2][1] - p[i][3][1]) / (p[i][2][0] - p[i][3][0]);
  b =  p[i][3][1] - (p[i][3][0] * m);
  softX = p[i][3][0] - (p[i][2][0] - p[i][3][0]) + (Math.random() * 2);
  softY = (softX * Math.random()) * m + b +  + (Math.random() * 2);

  dirX = p[i][4][2];
  dirY = p[i][4][3];
  
  if (rand) {
    dirX = ((Math.random() < 0.5) ? -1 : 1);
    dirY = ((Math.random() < 0.5) ? -1 : 1);
  }
  
  x = calcBezierX(p[i][4][0], i);
  y = calcBezierY(p[i][4][0], i);
  
  // interpolation points
  p[i][0][0] = p[i][5][0] = x;
  p[i][0][1] = p[i][5][1] = y;
  p[i][3][0] = checkBoundsX( p[i][0][0] + ((Math.random() * _variableDiffH) + _constantDiffH) * dirX );
  p[i][3][1] = checkBoundsY( p[i][0][1] + ((Math.random() * _variableDiffV) + _constantDiffV) * dirY );
  p[i][1][0] = softX;
  p[i][1][1] = softY;
  p[i][2][0] = checkBoundsX( p[i][3][0] + _controlRadius * Math.cos(Math.random()) );
  p[i][2][1] = checkBoundsY( p[i][3][1] + _controlRadius * Math.sin(Math.random()) );

  /*alert(p[i][0][0] + ", " + p[i][0][1] + "\n" +
        p[i][1][0] + ", " + p[i][1][1] + "\n" +
        p[i][2][0] + ", " + p[i][2][1] + "\n" +
        p[i][3][0] + ", " + p[i][3][0]);*/

  p[i][4][0] = 0.0;
}

function handleCollision(i) {
  newPathSegment(i, false);
}

function calcBezierX(t, i) {
  x =                     (1.0 - t) * (1.0 - t) * (1.0 - t) * p[i][0][0] +
        3.0 * t *         (1.0 - t) * (1.0 - t)           * p[i][1][0] +
        3.0 * t * t *     (1.0 - t)                     * p[i][2][0] +
              t * t * t                               * p[i][3][0];
  if (x == Number.NaN) x = 0.0;
  return x;
}

function calcBezierY(t, i) {
  y =                     (1.0 - t) * (1.0 - t) * (1.0 - t) * p[i][0][1] +
        3.0 * t *         (1.0 - t) * (1.0 - t)           * p[i][1][1] +
        3.0 * t * t *     (1.0 - t)                     * p[i][2][1] +
              t * t * t                               * p[i][3][1];
  if (y == Number.NaN) y = 0.0;
  return y;
}

function checkBoundsX(x) {
  bounds = new Array( new Array(50, 50), new Array(_playgroundWidth, _playgroundHeight) );
    
  width = 25;
    
  if (x < bounds[0][0])
    x = bounds[0][0] + Math.abs(x - bounds[0][0]);
      
  if ((x + width) > bounds[1][0])
    x = bounds[1][0] - Math.abs((x + width) - bounds[0][0]);
    
  return x;    
}

function checkBoundsY(y) {
  bounds = new Array( new Array(50, 50), new Array(_playgroundWidth, _playgroundHeight) );

  height = 25;

  if (y < bounds[0][1])
    y = bounds[0][1] + Math.abs(y - bounds[0][1]);
      
  if ((y + height) > bounds[1][1])
    y = bounds[1][1] - Math.abs((y + height) - bounds[1][1]);

  return y;    
}

function checkCollision(i) {
  bounds = new Array( new Array(50, 50), new Array(_playgroundWidth, _playgroundHeight) );
  
  x = p[i][5][0];
  y = p[i][5][1];
  
  r = false;
  width = 25;
  height = 25;
  
  if ((x < bounds[0][0]) && (p[i][4][2] != 1)) {
    p[i][4][2] = 1;
    handleCollision(i);
    r = true;
  }
  if (((x + width) > bounds[1][0]) && (p[i][4][2] != -1)) {
    p[i][4][2] = -1;
    handleCollision(i);
    r = true;
  }
  if ((y < bounds[0][1]) && (p[i][4][3] != 1)) {
    p[i][4][3] = 1;
    handleCollision(i);
    r = true;
  }
  if (((y + height) > bounds[1][1]) && (p[i][4][3] != -1)) {
    p[i][4][3] = -1;
    handleCollision(i);
    r = true;
  }
  
  if (!r) {
   
    for (n = _numOfAnimations; n-- > 0;) {
      if (i != n) {
        if ((((x > p[n][5][0]) && (x < (p[n][5][0] + width))) &&
             ((y > p[n][5][1]) && (y < (p[n][5][1] + height)))) ||
            ((((x + width) > p[n][5][0]) && ((x + width) < (p[n][5][0] + width))) &&
             (((y + height) > p[n][5][1]) && ((y + height) < (p[n][5][1] + height))))) {
          p[i][4][2] = p[n][4][2] * -1;
          p[i][4][3] = p[n][4][3] * -1;
          if (_colorChange) {
            p[i][4][4] = (p[i][4][4] + 1) % 2;
            p[n][4][4] = (p[n][4][4] + 1) % 2;
          }
          if (_collisionStop) {
            if ((Math.random() * 100) < 50)
              p[i][4][5] = (p[i][4][5] + 1) % 2;
            else
              p[n][4][5] = (p[n][4][5] + 1) % 2;
          }
          handleCollision(i);
          handleCollision(n);
          r = true;
        }
      }
    }
    
  }
  
  return r;
}

function animate() {
  
  if (_point.length == 0) {
    for (i = 0; i < _numOfAnimations; i++) {
      _point[i]      = document.getElementById('point_' + i);
      _pointImage[i] = document.getElementById('point_' + i + "_image");
    }
  }
  
  for (i = 0; i < _numOfAnimations; i++) {
  
    if ((_fadeIn) && (p[i][4][7] < 100)) ++p[i][4][7];
    else p[i][4][7] = 100;
  
    if ((_rotation) && (_rotationAfterStop || (p[i][4][5] == 0))) {
      p[i][4][6] = ((p[i][4][6] < 8) ? p[i][4][6] + 1 : 0);
    }
  
    if (p[i][4][5] == 0) {
      p[i][4][0] = Math.min(p[i][4][0] + (1.0 / p[i][4][1]), 1);
    }
    
    x = Math.min(0.0 + calcBezierX(p[i][4][0], i), _playgroundWidth - 25);
    y = 0.0 + calcBezierY(p[i][4][0], i);
      
    p[i][5][0] = x;
    p[i][5][1] = y;
      
    _point[i].style.left    = Math.floor(x) + "px";
    _point[i].style.top     = Math.floor(y) + "px";
    _point[i].style.opacity = (_fadeIn) ? Math.max(p[i][4][7] / 100.0) : 1;
    _point[i].style.filter = "alpha(opacity = " + p[i][4][7] + ")";
    _pointImage[i].src      = _imageData[(p[i][4][4] * 10) + p[i][4][6]].src;
    
    if ((!checkCollision(i)) && (p[i][4][0] == 1))
      newPathSegment(i, true);
      
  }
  
  //document.getElementById('debug').innerHTML = debug;
  
  window.setTimeout('animate();', _refreshTime);
    
}

function refresh() {
  init(false);
}
