/* canvas_saver.js - Paul Seamons - License BSD - Copyright 2007 */
/* $Id: canvas_saver.js,v 1.10 2007-11-21 05:16:26 paul Exp $ */

function canvas_saver (args) {
  // setup the initial canvas element
  var el = args.obj;
  if (! el && args.id) {
    el = document.getElementById(args.id);
  }
  if (! el) return;
  if (! el.tagName) {
    alert("The element must be a proper html element node");
    return;
  }
  if (el.tagName != 'CANVAS') {
    var canvas = document.createElement('CANVAS');
    canvas.setAttribute('width',  el.clientWidth);
    canvas.setAttribute('height', el.clientHeight);
    el.style.padding = '0px';
    if (el.tagName == 'BODY') el.style.margin  = '0px';
    el.insertBefore(canvas, el.firstChild);
    el = canvas;
  }

  // size, context and max_lines
  if (! el.getContext) return;
  var c = el.getContext('2d');
  var w = el.clientWidth;
  var h = el.clientHeight;
  var max_lines = args.max_lines;
  var _ie = navigator.appVersion.indexOf('MSIE') != -1;
  if (! max_lines) max_lines = _ie ? 10 : 20;

  // setup line generation and random directions
  var lines = [];
  var dx = w / 100; if (dx < 2) dx = 2;
  var dy = h / 100; if (dy < 2) dy = 2;
  var dx1 = dx * (1 + Math.random());
  var dy1 = dy * (1 + Math.random());
  var dx2 = -dx * (1 + Math.random());
  var dy2 = -dy * (1 + Math.random());
  var unshift_new_line = function () {
    var ol = lines[0];
    var nl = {
      x1: ol.x1 + dx1,
      y1: ol.y1 + dy1,
      x2: ol.x2 + dx2,
      y2: ol.y2 + dy2
    };
    if (nl.x1 > w) { nl.x1 = w; dx1 *= -1 }
    if (nl.y1 > h) { nl.y1 = h; dy1 *= -1 }
    if (nl.x2 > w) { nl.x2 = w; dx2 *= -1 }
    if (nl.y2 > h) { nl.y2 = h; dy2 *= -1 }
    if (nl.x1 < 1) { nl.x1 = 1; dx1 *= -1 }
    if (nl.y1 < 1) { nl.y1 = 1; dy1 *= -1 }
    if (nl.x2 < 1) { nl.x2 = 1; dx2 *= -1 }
    if (nl.y2 < 1) { nl.y2 = 1; dy2 *= -1 }
    lines.unshift(nl);
  };

  // now generate the first lines
  lines[0] = {
    x1: Math.random()*w,
    x2: Math.random()*w,
    y1: Math.random()*h,
    y2: Math.random()*h
  };
  if (args.initial_lines) for (var i = 0; i < args.initial_lines && i < max_lines - 1; i++) unshift_new_line();

  // set initial colors
  var color = [args.initial_rgb ? args.initial_rgb : [255, 0, 0]];
  var dir   = [0,0,0];
  for (var i = 1; i < max_lines; i++) color[i] = [];
  var bgcolor = args.background;
  if (! bgcolor) bgcolor = "black";
  if (bgcolor == 'transparent') bgcolor = "rgba(255,255,255,0)";

  // function to reapply colors
  var set_colors = function () {
    for (var i = 1; i < max_lines; i++)
      for (var j = 0; j < 3; j++)
        color[i][j] = parseInt(color[0][j] * (max_lines - i * .9) / max_lines);
  };
  set_colors();

  // function to change color
  var morph_color = function () {
    var c = color[0];
    var d = dir;
    var j = d[0] ? 0 : d[1] ? 1 : 2;
    var i = (j == 0) ? 2 : j - 1;
    var k = (j == 2) ? 0 : j + 1;

    if (d[j] > 0) {
      if (c[j] == 255) {
        d[i] = -1;
        d[j] = d[k] = 0;
      }
    } else {
      if (c[j] == 0) {
        d[i] = 1;
        d[j] = d[k] = 0;
      }
    }

    for (var i = 0; i < 3; i++) {
      c[i] += d[i] * 10; // step;
      if (c[i] > 255) c[i] = 255;
      if (c[i] < 0)   c[i] = 0;
    }

    set_colors();
  };

  // function that runs everything
  var count = 0;
  var canvas_saver_run = function () {
    count++;
    c.clearRect(0,0,w,h);
    //c.globalCompositeOperation = 'copy'; // necessary for transparency color
    c.fillStyle = bgcolor;
    c.fillRect(0, 0, w, h);
    //c.globalCompositeOperation = 'source-over';
    c.save();

    c.lineWidth = 2;
    for (var i = lines.length - 1; i >= 0; i--) {
      c.beginPath();
      c.strokeStyle = 'rgb('+color[i]+')';
      c.moveTo(lines[i].x1, lines[i].y1);
      c.lineTo(lines[i].x2, lines[i].y2);
      c.stroke();
      c.closePath();
    }

    unshift_new_line();
    if (lines.length > max_lines) lines.pop();

    if (count % 1000) morph_color();

    c.restore();
  };

  // initialize
  canvas_saver_run();

  // get functions to allow for start/stop
  var temp = {};
  temp.is_running = false;
  var stopper = {
    stop:  function () { if (! temp.is_running) return; temp.is_running = false; clearInterval(temp.timer) },
    start: function () { if (  temp.is_running) return; temp.is_running = true;  temp.timer = setInterval(canvas_saver_run, 50) },
    is_ie: _ie
  };

  // allow onmouseup to start and stop us also
  el.onmouseup = function () { temp.is_running ? stopper.stop() : stopper.start() }

  if (args.start) stopper.start();

  return stopper;
}
