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(), randomDirection()];
}

function slp(p1, p2) {
  return (p2[1] - p1[1]) / (p2[0] - p1[0]);
}

function theta(p1, p2) {
  return Math.atan(slp(p1, p2));
}

var Arc = klass.create();
Object.extend(Arc.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.points = [new Point([20, 20], 10, randDir()),
		   new Point([125, 5], 10, randDir()),
		   new Point([300, 127], 10, randDir()),
		   new Point([500, 280], 10, randDir()),
		   new Point([100, 200], 10, randDir()),
		   new Point([50, 50], 10, randDir()),
		   new Point([30, 30], 10, randDir()),
		   new Point([30, 30], 10, randDir()),
		   new Point([30, 30], 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();
  },

  drawShade: function(point, size) {
    var g = this.g;
    g.beginPath();
    var m = slp(point, [0, 0]);
    g.moveTo(point[0], point[1]);
    g.lineTo(point[0]*size*Math.cos(m), point[1]*size*Math.sin(m));
    g.lineTo(point[0]*size*Math.cos(m/2), point[1]*size*Math.sin(m/2));
    g.closePath();
    g.fill();
  },

  drawTriangle: function(point, size) {
    var g = this.g;
    g.beginPath();
    size = 50;
    var sBig = Math.PI*2*0.45;
    var sSmall = Math.PI*2*0.1;
    var focus = this.application.focusPoint;
    var a = theta(focus, point);
    g.strokeStyle = "rgba(255, 255, 255, 1)";
    g.moveTo(point[0], point[1]);
    if (focus[0] > point[0]) {
      g.moveTo(point[0]+size*Math.cos(a), point[1]+size*Math.sin(a));
      a+=sBig;
      g.lineTo(point[0]+size*Math.cos(a), point[1]+size*Math.sin(a));
      a+=sSmall;
      g.lineTo(point[0]+size*Math.cos(a), point[1]+size*Math.sin(a));
      a+=sBig;
      g.lineTo(point[0]+size*Math.cos(a), point[1]+size*Math.sin(a));
    } else {
      g.moveTo(point[0]-size*Math.cos(a), point[1]-size*Math.sin(a));
      a+=sBig;
      g.lineTo(point[0]-size*Math.cos(a), point[1]-size*Math.sin(a));
      a+=sSmall;
      g.lineTo(point[0]-size*Math.cos(a), point[1]-size*Math.sin(a));
      a+=sBig;
      g.lineTo(point[0]-size*Math.cos(a), point[1]-size*Math.sin(a));
    }

    // g.moveTo(point[0], point[1]);
    // g.lineTo(point[0]-size*Math.cos(a), point[1]-size*Math.sin(a));
    // g.closePath();
    g.fill();
    g.stroke();
  },

  plotBezier: function(g, p0, p1, p2, size) {
    var t=0;
    var s=0.08;
    while (t <= 1) {
      var t1 = (1-t);
      var t2 = t1*t1;
      var x = t2*p0[0] + 2*t1*t*p1[0] + t*t*p2[0];
      var y = t2*p0[1] + 2*t1*t*p1[1] + t*t*p2[1];
      var point = [x,y];
      this.drawTriangle(point, 5);
      // this.drawCircle(point, 5);
      t+=s;
    }
  },

  onEnterFrame: function() {
    var g = this.g;
    g.save();
    g.fillStyle = colorDef(this.color, 0.5);
    for (var i=0; i<this.points.length;++i) {
      this.advance(this.points[i]);
      // this.points[i].render(g);
    }
    this.plotBezier(g,
                    this.points[0].point,
		    this.points[1].point,
		    this.points[2].point,
		    this.size);
    this.plotBezier(g,
                    this.points[2].point,
		    this.points[3].point,
		    this.points[4].point,
		    this.size);
    this.plotBezier(g,
                    this.points[4].point,
		    this.points[5].point,
		    this.points[6].point,
		    this.size);
    this.plotBezier(g,
                    this.points[6].point,
		    this.points[7].point,
		    this.points[0].point,
		    this.size);
    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.currentPoint = null;
    this.focusPoint = [this.root.width/2,
                       this.root.height/2];
    this.arc = new Arc(this, this.root);

    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));
    
  },

  onMouseDown: function(evt) {
    var point = this.getClosestPoint(evt);
    if (!point) return;
    this.currentPoint = point;
  },

  onMouseUp: function(evt) {
    this.currentPoint = null;
  },

  onMouseMove: function(evt) {
    var point = this.root.translateScenePosition(evt);
    if (this.currentPoint) {
      this.currentPoint.point = point;
    }

    this.focusPoint = point;
  },

  getClosestPoint: function(evt) {
    // not used...
    var minDistance = Number.MAX_VALUE;
    var index = -1;
    var mousePos = this.root.translateScenePosition(evt);
    var points = this.arc.points;
    for (var i=0; i<points.length; ++i) {
      var point = points[i];
      var dist = getDistance(mousePos, point.point);
      if (dist<minDistance) {
	minDistance = dist
	index = i;
      }
    }

    if (index == -1) return;

    if (minDistance < points[index].size/2) {
      return points[index];
    }
    return null;
  },
});

var g_application = null;

function main() {
  g_application = new Application();
}

document.observe('dom:loaded', this.main.bind(this));
// vim: set sts=2 sw=2:
