// Layout container to handle one container with lm_left, lm_right, lm_top, lm_bottom, and lm_center
rio.LayoutContainer = Class.create({
  initialize: function(root) {   
    this.parent = $(root.parentNode); 
    root.setStyle("padding:0; margin:0; border:0"); 
    // Pre-compute paddings
    $w("top left right bottom").each(function(key) { 
      this.parent[key] = this.padding(this.parent, key);
    }.bind(this));
    
    // Init arrays
    $w("lm_top lm_left lm_right lm_bottom lm_center").each(function(key) {
      this[key] = [];
    }.bind(this));
    
    root.childElements().each(function(element) {
      element.style.position = "absolute";
      element.paddingWidth   = this.fullPadding(element, "left") + this.fullPadding(element, "right");
      element.paddingHeight  = this.fullPadding(element, "top") + this.fullPadding(element, "bottom");
      element.marginWidth    = this.margin(element, "left") + this.margin(element, "right");
      element.marginHeight   = this.margin(element, "top") + this.margin(element, "bottom");
      
      if (element.hasClassName("lm_top")) {
        this.lm_top.push(element);
      } else if (element.hasClassName("lm_left")) {
        this.lm_left.push(element);  
      } else if (element.hasClassName("lm_right")) {
        this.lm_right.unshift(element);
      } else if (element.hasClassName("lm_bottom")) {
        this.lm_bottom.unshift(element);  
      } else if (element.hasClassName("lm_center")) {
        if (this.lm_center.length > 0) {
          throw("Only one lm_center per lm_container");
		}
        this.lm_center.push(element);
      }
    }.bind(this));
  },
  
  updateSize: function() {      
    var d = this.parent.getDimensions();
    var w = d.width - this.parent.left - this.border(this.parent, "left") - this.border(this.parent, "right");
    var h = d.height - this.parent.top - this.parent.bottom  - this.border(this.parent, "top") - this.border(this.parent, "bottom");
    var that = this; // To avoid too many binds
   
    // Set position and size of all top elements  
    var top = this.parent.top;     
    this.lm_top.each(function(element) {   
      var s = element.style;   
      that.setPositivePxValue(s, 'width', w - element.paddingWidth);
      s.top = top + "px";
      top += element.getHeight() + element.marginHeight;
    });
    h -= top - this.parent.top;
    
    // Set position and size of all bottom elements
    var bottom = this.parent.bottom;
    this.lm_bottom.each(function(element) { 
      var s = element.style;   
      that.setPositivePxValue(s, 'width', w - element.paddingWidth);
      s.bottom = bottom + "px";
      bottom += element.getHeight() + element.marginHeight;
    });
    h -= bottom - this.parent.bottom;
     
    // Set position and size of all left elements
    var left = this.parent.left;          
    this.lm_left.each(function(element) {
      var s = element.style;  
      that.setPositivePxValue(s, 'height', h - element.paddingHeight);
      s.top  = top + "px";  
      s.left = left + "px";  
      left += element.getWidth() + element.marginWidth;
    });
    w -= left;
    
    // Set position and size of all right elements
    var right = this.parent.right;
    this.lm_right.each(function(element) {
      var s = element.style;
      that.setPositivePxValue(s, 'height', h - element.paddingHeight);
      s.top   = top + "px";  
      s.right = right + "px";  
      right += element.getWidth() + element.marginWidth;
    });
    w -= right;
     
    // Set position and size of all center elements
    // Only one center for this version
    var center = this.lm_center.first();
    var s = center.style;
    s.top  = top + "px"; 
    s.left = left + "px";  
    this.setPositivePxValue(s, 'width', w - center.paddingWidth);
    this.setPositivePxValue(s, 'height', h - center.paddingHeight);
  },
     
  // Private functions
  fullPadding: function(element, s) {   
    return this.padding(element, s) + this.border(element, s) + this.margin(element, s);
  },

  border: function(element, s) {   
    var border = parseInt(element.getStyle("border-" + s + "-width") || 0, 10);
    if (isNaN(border)) { // Test for IE!!
      border = 0;
	}
    return border;
  },

  padding: function(element, s) {   
    var padding = parseInt(element.getStyle("padding-" + s) || 0, 10);
    if (isNaN(padding)) {   // Test for IE!!
       padding = 0;
	}
    return padding;
  },

  margin: function(element, s) {   
    var margin = parseInt(element.getStyle("margin-" + s) || 0, 10);
    if (isNaN(margin)) {  // Test for IE!!
       margin = 0;
	}
    return margin;
  },
  
  setPositivePxValue:function(objet, key, value) {
    objet[key] =  (value > 0 ? value : 0) + "px";
  }
});
                 
// Layout manager: handles N layout container
rio.LayoutManager = Class.create({
  initialize: function(root) {
    this.root = root || document.body;
    this.init();
    Event.observe(window, "resize", this.resize.bind(this));
  },
  
  reset: function() {
    this.init.bind(this).defer();
  }, 
  
  add: function(root) {       
    this.addElement.bind(this, root, true).defer();
  },
  
  // Private functions
  init: function() {
    this.containers = [];
    this.addElement(this.root);  
    this.resize();    
  },
  
  resize: function() {
   	this.containers.invoke("updateSize"); 
  },
  
  addElement: function(element, doResize) {
    $(element).getElementsBySelector(".lm_container").each(function(element) {
      this.containers.push(new rio.LayoutContainer(element));
    }.bind(this));
    if (doResize) {
      this.resize();
	}
  }
});