var ElementMaxHeight = function() {
  this.initialize.apply(this, arguments);
}

/**
 * ElementMaxHeight constructor
 * @param string cssQuery
 * @param ...
 * 
 * cssQuery format is '[tag](#|.)(selectorName)[:parent]' where:
 *   [] - optional, () - required
 *   tag - (X)HTML tag name
 *   #|. - id or class separator
 *   selectorName - id or class name
 *   :parent - refers to element's parent node
 * Example:
 *   ElementMaxHeight('.maxheight', 'br.vspacer:parent');
 *   // expands all elements with class 'maxheight'
 *   // and all blocks containing <br class="vspacer" />
 */
ElementMaxHeight.prototype = {
  initialize: function() {
    var __args = arguments;
    var __object = this;
    var __run = this.run;
    if (window.addEventListener) {
      window.addEventListener('load', function() {return __run.apply(__object, __args)}, false);
    } else if (window.attachEvent) {
      window.attachEvent('onload', function() {return __run.apply(__object, __args)});
    }
  },

  run: function() {
    this.elements = this.findElements(arguments);
    this.textElement = document.createElement('span');
    this.textElement.appendChild(document.createTextNode('A'));
    this.textElement.style.display = 'block';
    this.textElement.style.position = 'absolute';
    this.textElement.style.fontSize = '1em';
    this.textElement.style.top = '-1000px';
    this.textElement.style.left = '-1000px';
    document.body.appendChild(this.textElement);
    this.textElementHeight = this.textElement.offsetHeight;
    var __object = this;
    var __checkFontSize = this.checkFontSize;
    this.checkFontSizeInterval = window.setInterval(function() {return __checkFontSize.apply(__object)}, 500);

    this.expand();

    // Refresh elements height onResize event
    var __expand = this.expand;
    if (window.addEventListener) {
      window.addEventListener('resize', function(event) {return __expand.apply(__object, [( event || window.event)])}, false);
    } else if (window.attachEvent) {
      window.attachEvent('onresize', function(event) {return __expand.apply(__object, [( event || window.event)])});
    }
  },
  
  findElements: function(cssQuery) {
    var elements = [], items = [], item;
    for (var i = 0; i < cssQuery.length; i++) {
      // Explode cssQuery: ["tagName", "# | .", "Id | className", ":", "parent"]
      var q = cssQuery[i].replace(/\.|\:|#]/gi, ',$&,').split(',');
      if (q[1] == '#') { // find by Id
        if (q[4] && q[4] == 'parent') {
          item = document.getElementById(q[2]).parentNode;
        } else {
          item = document.getElementById(q[2]);
        }

        if (q[0].length == 0 || q[0] == '*' || (q[0].length > 0 && q[0].toLowerCase() == item.tagName.toLowerCase())) {
          elements.push(item);
        }
      } else if (q[1] == '.') { // find by className
      
          items = document.getElementsByClassName(q[2]);
       
        for (var j = 0; j < items.length; j++) {            
          if (q[0].length == 0 || q[0] == '*' || (q[0].length > 0 && q[0].toLowerCase() == items[j].tagName.toLowerCase())) {
            elements.push((q[4] && q[4] == 'parent') ? items[j].parentNode : items[j]);
          }
        }
      }
    }

    return elements;
  },

  expand: function() {
    this.reset();
    for (var i = 0; i < this.elements.length; i++) {
      var col = getBoxLayout(this.elements[i]);
      this.elements[i].style.height = (
        getBoxLayout(this.elements[i].parentNode).height
        - (col.marginTop + col.marginBottom
           + col.borderTop + col.borderBottom
           + col.paddingTop + col.paddingBottom)) + 'px';
  	}
  },

  reset: function() {
    for (var i = 0; i < this.elements.length; i++) {    
      this.elements[i].style.height = 'auto';
    }
  },

  checkFontSize: function() {
  	var height = this.textElement.offsetHeight;
  	if(this.textElementHeight != height) {
  		this.textElementHeight = height;
  		this.expand();
  	}
  }
}

document.getElementsByClassName = function(className, parentElement) {
  if (!!document.evaluate) {
    var results = [];
    var query = document.evaluate(
        ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]",
        parentElement || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++) {
      results.push(query.snapshotItem(i));
    }
    return results;
  } else {
    var children = (parentElement || document.body).getElementsByTagName('*');
    var elements = [], child;
    for (var i = 0, length = children.length; i < length; i++) {
      child = children[i];
      if (child.className.length != 0 &&
          (child.className == className ||
           child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))) {
        elements.push(child);
      }
    }
    return elements;
  }
}

function getStyle(element, style) {
   if (window.getComputedStyle) {
    return window.getComputedStyle(element, null)[style];
  } else if (element.currentStyle) {
    return element.currentStyle[style];
  }
}

function getBoxLayout(element) {
    var styleNames = {
      'marginTop': 'marginTop', 'marginRight': 'marginRight',
      'marginLeft': 'marginLeft', 'marginBottom': 'marginBottom',
      'borderTopWidth': 'borderTop', 'borderRightWidth': 'borderRight',
      'borderLeftWidth': 'borderLeft', 'borderBottomWidth': 'borderBottom',
      'paddingTop': 'paddingTop', 'paddingRight': 'paddingRight',
      'paddingLeft': 'paddingLeft', 'paddingBottom': 'paddingBottom'
    };

    var box = {}, value = 0;
    for (var styleName in styleNames) {
      value = getStyle(element, styleName);
      box[styleNames[styleName]] = isNaN(parseInt(value)) ? 0 : parseInt(value);
    }
    box.width = element.offsetWidth - (box.paddingLeft + box.paddingRight + box.borderLeft + box.borderRight);
    box.height = element.offsetHeight - (box.paddingTop + box.paddingBottom + box.borderTop + box.borderBottom);
    return box;
};

// Create new ElementMaxHeight instance
new ElementMaxHeight(
	'.column_center',
	'.indent_center',
	'.side_bar',
	'.inside',
	'.equal'
);
