/*****************************************************************************/
/* Imports */
/*****************************************************************************/
var debug = Iron.utils.debug('iron:controller');
var Layout = Iron.Layout;
var DynamicTemplate = Iron.DynamicTemplate;

/*****************************************************************************/
/* Private */
/*****************************************************************************/
var bindData = function (value, thisArg) {
  return function () {
    return (typeof value === 'function') ? value.apply(thisArg, arguments) : value;
  };
};

/*****************************************************************************/
/* Controller */
/*****************************************************************************/
Controller = function (options) {
  var self = this;
  this.options = options || {};
  this._layout = this.options.layout || new Layout(this.options);
  this._isController = true;
  this._layout._setLookupHost(this);

  // grab the event map from the Controller constructor which was
  // set if the user does MyController.events({...});
  var eventMap = this.constructor._collectEventMaps();
  this._layout.events(this.constructor._eventMap, this);

  this.init(options);
};

/**
 * Set or get the layout's template and optionally its data context.
 */
Controller.prototype.layout = function (template, options) {
  var result = this._layout.template(template);

  // check whether options has a data property
  if (options && (_.has(options, 'data')))
    this._layout.data(bindData(options.data, this));

  return result;
};

/**
 * Render a template into a region of the layout.
 */
Controller.prototype.render = function (template, options) {
  if (options && (typeof options.data !== 'undefined'))
    options.data = bindData(options.data, this);
  return this._layout.render(template, options);
};

/**
 * Begin recording rendered regions.
 */
Controller.prototype.beginRendering = function (onComplete) {
  return this._layout.beginRendering(onComplete);
};

/*****************************************************************************/
/* Controller Static Methods */
/*****************************************************************************/
/**
 * Inherit from Controller.
 *
 * Note: The inheritance function in Meteor._inherits is broken. Static
 * properties on functions don't get copied.
 */
Controller.extend = function (props) {
  return Iron.utils.extend(this, props); 
};

Controller.events = function (events) {
  this._eventMap = events;
  return this;
};

/**
 * Returns a single event map merged from super to child.
 * Called from the constructor function like this:
 *
 * this.constructor._collectEventMaps()
 */

var mergeStaticInheritedObjectProperty = function (ctor, prop) {
  var merge = {};

  if (ctor.__super__)
    _.extend(merge, mergeStaticInheritedObjectProperty(ctor.__super__.constructor, prop));
  
  return _.has(ctor, prop) ? _.extend(merge, ctor[prop]) : merge;
};

Controller._collectEventMaps = function () {
  return mergeStaticInheritedObjectProperty(this, '_eventMap');
};

// NOTE: helpers are not inherited from one controller to another, for now.
Controller._helpers = {};
Controller.helpers = function (helpers) {
  _.extend(this._helpers, helpers);
  return this;
};

/*****************************************************************************/
/* Global Helpers */
/*****************************************************************************/
if (typeof Template !== 'undefined') {
  /**
   * Returns the nearest controller for a template instance. You can call this
   * function from inside a template helper.
   *
   * Example:
   * Template.MyPage.helpers({
   *   greeting: function () {
   *    var controller = Iron.controller();
   *    return controller.state.get('greeting');
   *   }
   * });
   */
  Iron.controller = function () {
    return DynamicTemplate.findLookupHostWithProperty(Blaze.getView(), '_isController');
  };

  /**
   * Find a lookup host with a state key and return it reactively if we have
   * it.
   */
  Template.registerHelper('get', function (key) {
    var controller = Iron.controller();
    if (controller && controller.state)
      return controller.state.get(key);
  });
}
/*****************************************************************************/
/* Namespacing */
/*****************************************************************************/
Iron.Controller = Controller;

@@ -1152,31 +1152,25 @@
 ntMap = 
-this.c
+C
 on
-s
 tr
-ucto
+olle
 r._colle
@@ -1180,17 +1180,38 @@
 ventMaps
-(
+.call(this.constructor
 );%0A  thi
@@ -1227,34 +1227,16 @@
 .events(
-this.constructor._
 eventMap
@@ -1419,16 +1419,23 @@
 var 
-result =
+self = this;%0A%0A 
  thi
@@ -1622,14 +1622,99 @@
 urn 
-result
+%7B%0A    data: function (val) %7B%0A      return self._layout.data(bindData(val, self));%0A    %7D%0A  %7D
 ;%0A%7D;
@@ -1834,16 +1834,36 @@
 ions) %7B%0A
+  var self = this;%0A%0A
   if (op
@@ -1955,32 +1955,37 @@
 ata, this);%0A
+%0A
   
-return
+var tmpl =
  this._layou
@@ -2004,32 +2004,205 @@
 plate, options);
+%0A%0A  // allow caller to do: this.render('MyTemplate').data(function () %7B...%7D);%0A  return %7B%0A    data: function (func) %7B%0A      return tmpl.data(bindData(func, self));%0A    %7D%0A  %7D;
 %0A%7D;%0A%0A/**%0A * Begi

make it okay if _collectEventMaps isn't defined