
var LT = {};
LT = function(elem) {
  this.jq = $("#"+elem);
  this.elem = this.jq[0];
  this.elem.layout = this;
  this.paper = Raphael(elem, this.jq.width(), this.jq.height());
  this.bbox = { x1: undefined, y1: undefined, x2: undefined, y2: undefined };
  this.blocks = [];
};


LT.prototype._update_bbox = function(x,y) {
  var b = this.bbox;
  if ( (typeof(b.x1) == 'undefined') || x < b.x1 ) b.x1 = x;
  if ( (typeof(b.y1) == 'undefined') || y < b.y1 ) b.y1 = y;
  if ( (typeof(b.x2) == 'undefined') || x > b.x2 ) b.x2 = x;
  if ( (typeof(b.y2) == 'undefined') || y > b.y2 ) b.y2 = y;
};


LT.prototype._adjust_pt = function(x,y,attrs) {
  var ox = x, oy = y;

  // Rotate first:
  var rot = parseInt(attrs.rotation);
  if      ( rot == 1 ) { var t=x; x=-y; y=t; attrs.m=[0,-1,1,0,0,0]; }
  else if ( rot == 2 ) { x=-x; y=-y; attrs.m=[-1,0,0,-1,0,0]; }
  else if ( rot == 3 ) { var t=x; x=y; y=-t; attrs.m=[0,1,-1,0,0,0]; }
  
  // Reflection is almost the same as rotation.  won't have
  // both rotation and reflection
  var ref = parseInt(attrs.reflection);
  if      ( ref == 1 ) { y=-y; attrs.m=[1,0,0,-1,0,0]; }
  else if ( ref == 2 ) { x=-x; attrs.m=[-1,0,0,1,0,0]; }

  if ( !attrs.m ) { attrs.m=[1,0,0,1,0,0]; }

  // Now translate:
  var dx = parseFloat(attrs['x_trans']) || 0;
  var dy = parseFloat(attrs['y_trans']) || 0;
  x += dx;
  y += dy;
  attrs.m[4] = dx;
  attrs.m[5] = dy;

  return [x,y];
};


LT.prototype.block = function(block,attrs) {
  attrs.name = block;
  this.blocks.push(attrs);

  var ll = this._adjust_pt(attrs.bbox_lx,attrs.bbox_ly,attrs);
  var ur = this._adjust_pt(attrs.bbox_ux,attrs.bbox_uy,attrs);

  this._update_bbox(ll[0],ll[1]);
  this._update_bbox(ur[0],ur[1]);
};


LT.prototype.draw = function() {
  this.g = this.paper.group();

  // Calculate dimensions
  this.bbox.w = this.bbox.x2 - this.bbox.x1;
  this.bbox.h = this.bbox.y2 - this.bbox.y1;
  this.elem_w = this.jq.width();
  this.elem_h = this.jq.height();


  this.scale_w = this.bbox.w / this.elem_w;
  this.scale_h = this.bbox.h / this.elem_h;
  this.scale = this.scale_w > this.scale_h ? this.scale_w : this.scale_h;
  this.scale = (1 / this.scale) * 0.90;


  // Draw block outlines
  for ( var i=0, n=this.blocks.length; i<n; i++ ) {
    var block = this.blocks[i];
    this._drawBlock(this.g,block);
  }


  // normalize all drawing to 0,0
  this.g.translate(-this.bbox.x1,-this.bbox.y1);
  //console.debug("1st translate -" + this.bbox.x1 + ",-" + this.bbox.y1);

  // Scale to fit
  this.g.scale ( this.scale, this.scale );
  //console.debug("scale " + this.scale);

  // center all drawing in the paper
  this.g.translate((this.elem_w - this.bbox.w)*.5,
		   (this.elem_h - this.bbox.h)*.5);
  //console.debug("second translate " + ((this.elem_w-this.bbox.w)*.5) +
  //		"," + ((this.elem_h-this.bbox.h)*.5) );

};



LT.prototype._drawBlock = function(g,block) {
  if ( block.path ) return;

  var linewidth = 1;
  if ( this.scale < 1.0 ) linewidth /= this.scale;
   var p = g.path({stroke:'white', 'stroke-width':linewidth+"px"});
   block.path = p;

  var boundary = block.boundary.split(':');
  for ( var i=0, n=boundary.length; i<n; i++ ) {
    var pt = boundary[i].split(',');
    if ( i == 0 ) p.moveTo(pt[0],pt[1]);
    else p.lineTo(pt[0],pt[1]);
  }
  p.andClose();

  var m = block.m;
  if ( m ) p.matrix(m[0],m[1],m[2],m[3],m[4],m[5]);

  p[0].onmouseover = function() { p.attr({fill:'red'}); };
  p[0].onmouseout = function() { p.attr({fill:''}); };

};

