var Point = klass.create();
Object.extend(Point.prototype, {
  initialize: function(point, size, direction) {
    this.point = point;
    this.size = size;
    this.direction = direction;
  },

  render: function(g) {
    g.beginPath();
    g.arc(this.point[0], this.point[1],
	  this.size/2, 0, Math.PI*2, 0);
    g.closePath();
    g.fill();
  }
});

function randDir() {
  return [randomDirection()*3, randomDirection()*3];
}

function slp(p1, p2) {
  return (p2[1] - p1[1]) / (p2[0] - p1[0]);
}

function theta(p1, p2) {
  return Math.atan(slp(p1, p2));
}

var Metaball = klass.create();
Object.extend(Metaball.prototype, {
  initialize: function(application, scene) {
    this.application = application;
    this.g = scene.graphics;
    this.scene = scene;
    this.scene.addChild(this);
    this.color = [255, 255, 255];
    this.point = new Point([100, 100], 10, randDir());
  },

  advance: function(point) {
    var sceneWidth = this.scene.width;
    var sceneHeight = this.scene.height;
    var oldPos = point.point;
    var newPos = [point.direction[0] + oldPos[0],
                  point.direction[1] + oldPos[1]];
    if ((newPos[0] > sceneWidth) || (newPos[0] < 0)) {
      point.direction[0] = -(point.direction[0]);
    }

    if ((newPos[1] > sceneHeight) || (newPos[1] < 0)) {
      point.direction[1] = -(point.direction[1]);
    }
    point.point = [point.direction[0] + oldPos[0],
                   point.direction[1] + oldPos[1]];
  },

  drawCircle: function(point, size) {
    var g = this.g;
    g.beginPath();
    g.arc(point[0], point[1],
	  size/2, 0, Math.PI*2, 0);
    g.closePath();
    g.fill();
  },

  onEnterFrame: function() {
    // var g = this.g;
    // g.save();
    // g.fillStyle = colorDef(this.color, 0.5);
    this.advance(this.point);
    // this.drawCircle(this.point.point, 4);
    // g.restore();
  }
});

var Application = klass.create();
Object.extend(Application.prototype, {
  initialize: function() {
    var cvs = $('drawing');
    if (!cvs.getContext) { return; }
    this.root = new Scene(cvs);

    this.mballs = [new Metaball(this, this.root),
                   new Metaball(this, this.root),
                   new Metaball(this, this.root),
                   new Metaball(this, this.root)];

    this.root.onEnterFrame = this.onEnterFrame.bind(this);
    Event.observe(this.root.canvas, 'mousedown',
		  this.onMouseDown.bind(this));
    Event.observe(this.root.canvas, 'mouseup',
		  this.onMouseUp.bind(this));
    Event.observe(this.root.canvas, 'mousemove',
		  this.onMouseMove.bind(this));
    
  },

  drawCircle: function(point, size) {
    var g = this.root.graphics;
    g.fillStyle = colorDef([255, 255, 255], 1);
    g.beginPath();
    // alert(point[0] + ":" + point[1]);
    g.arc(point[0], point[1], size/2, 0, Math.PI*2, 0);
    g.closePath();
    g.fill();
  },

  pixel: function(point, size) {
    var g = this.root.graphics;
    c = [Math.round((point[0]/this.root.width)*255),
         Math.round((point[1]/this.root.height)*255),
         255];
    g.fillStyle = colorDef(c, 1);
    g.fillRect(point[0], point[1], size, size);
  },

  onEnterFrame: function() {
    var gridStep = 8;
    for (var i=0; (i*gridStep)<this.root.height;++i) {
      for (var j=0; (j*gridStep)<this.root.width;++j) {
	var val = 0;
	var point = null;
	for (var k=0; k<this.mballs.length; ++k) {
	  point = [(j*gridStep), (i*gridStep)];
	  mbpoint = this.mballs[k].point.point;
	  var valx = mbpoint[0] - point[0];
	  valx = valx*valx;
	  var valy = mbpoint[1] - point[1];
	  valy = valy*valy;
	  // var val = 1/Math.sqrt(valx + valy);
	  // den = Math.sqrt(valx + valy);
	  den = valx + valy;
	  // if (den == 0) {
	  //   return;
	  // }

	  val += 7000/den;
	}

	if (val > 2.2 && val < 4) {
	  for (var y=point[1];y<point[1]+gridStep;y+=2) {
	    for (var x=point[0];x<point[0]+gridStep;x+=2) {
	      var p = [x, y];
	      var v = 0;
	      for (var b=0; b<this.mballs.length;++b) {
		var mb = this.mballs[b].point.point;
		var valx = mb[0] - p[0];
	  	valx = valx*valx;
	  	var valy = mb[1] - p[1];
	  	valy = valy*valy;
	  	den = valx + valy;
	  	v += 7000/den;
	      }
	      if ((v < 3.0) && (v > 2.80)) {
	        this.pixel(p, 2);
	      }
	    }
	  }
	  // this.root.graphics.strokeStyle = "rgba(255, 255, 255, 0.5)";
	  // this.root.graphics.strokeRect(point[0], point[1],
	  //       		        gridStep, gridStep);
	}
      }
    }
  },

  onMouseDown: function(evt) {
  },

  onMouseUp: function(evt) {
  },

  onMouseMove: function(evt) {
  }
});

var g_application = null;

function main() {
  g_application = new Application();
}

document.observe('dom:loaded', this.main.bind(this));
// vim: set sts=2 sw=2:
