//*@public
/**
  _enyo.Controller_ is a special type of _enyo.Component_ that is
  not intended for use in a components block (the components array).
*/
enyo.kind({
  name: "enyo.Controller",
  kind: "enyo.Component",
  mixins: ["enyo.MultipleDispatchMixin"],
  published: {
    data: null
  },
  //*@public
  /**
    In cases where a controller needs to proxy content from
    another controller, set this property to a _String_ or
    object reference to an instance of that kind. This could,
    for example, allow a controller of one kind to proxy content
    through another controller with a different implementation
    without the need to share the underlying data directly.
  */
  proxyController: null,
  //*@public
  /**
    Change this to the name of the desired property that is
    bound on this controller from the proxy controller.
  */
  proxyControllerTarget: "data",
  //*@public
  /**
    Change this to the name of the desired property that is
    to be bound from on the proxy controller.
  */
  proxyControllerSource: "data",
  //*@public
  /**
    Set this to true to disable automatic bindings on the proxy
    controller and set your own via the _bindings_ array.
  */
  proxyControllerDisableAutoBindings: false,
	//*@protected
	/**
	  By default _enyo.Controller_ does not wish to bubble events. This is
	  the case for view-owned controllers. Controllers with multiple
	  interested bubble targets are handled separately and incorporate
	  the _enyo.MultipleDispatchMixin_.
	*/
	getBubbleTarget: function () {
	  return this._bubbleTarget;
	},
	//*@protected
	/**
	  If a view creates an instance of a controller it sets itself as the
	  owner by default. This allows controllers intended to be aware of
	  the view that owns them, to bind on and interact with the owner
	  bidirectionally.
	*/
	ownerChanged: function () {
	  // generate a unique id
	  if (!this.id) this.id = this.makeId();
	  // refresh any bindings we have that target our owner
	  if (this._bindings && this._bindings.length) this.refreshBindings();
	},
    //*@protected
    _bubbleTarget: null,
	//*@protected
  create: function () {
    this.inherited(arguments);
    this.proxyControllerChanged();
  },
  //*@protected
  proxyControllerChanged: function () {
    this.findAndInstance("proxyController", function (ctor, inst) {
      // if we don't have an instance nothing to do
      if (!inst) return;
      if (ctor) {
        // we should never have a constructor because the proxy controller
        // can only be an instance of a controller not a class
        return enyo.warn("enyo.Controller: cannot use a controller class as a " +
          "proxy controller, must be a controller instance");
      }
      // so we have a proxy controller...
      if (this.proxyControllerDisableAutoBindings) return this.refreshBindings();
      else this.initProxyController();
    });
  },
  //*@protected
  initProxyController: function () {
    var proxy = this.proxyController, target = this.proxyControllerTarget,
        source = this.proxyControllerSource;
    if (!proxy) return;
    this.binding({source: proxy, from: source, to: target});
    proxy.addDispatchTarget(this);
  }
});
//*@public
/**
    The base class for all controllers in enyo. The _enyo.Controller_
    is a delegate/component that is designed to be a proxy of information.
    Rarely will it be necessary or useful to use this base-kind of controller
    and far more likely to need _enyo.ArrayController_ or subclasses.
*/
enyo.kind({
    //*@public
    name: "enyo.Controller",
    //*@protected
    // we inherit from component because we need to be able to use the bubble
    // and waterfall systems
    kind: "enyo.Component",
    //*@protected
    mixins: ["enyo.MultipleDispatchMixin"],
    //*@public
    /**
        For all _enyo.Controller_s and subkinds the default source of information
        is the _data_ property. In some cases this is a computed property for
        easier overloading. Can be any type of data.
    */
    data: null,
    //*@protected
    create: function () {
        this.inherited(arguments);
        // make sure we have some type of id
        this.id = this.makeId();
    },
    //*@protected
    ownerChanged: function () {
        this.refreshBindings();
    },
    //*@protected
    /**
        Typically controllers don't wish to bubble (component-owned controllers)
        but controllers with multiple event targets might.
    */
    controllerBubbleTarget: null,
    //*@protected
    // for now this is for backwards compatibility, soon to be removed
    // and instead call the normal getter
    getBubbleTarget: function () {
        return this.get("bubbleTarget");
    },
    //*@public
    /**
        The preferred retreival mechanism for the _bubbleTargeT_ for
        events.
    */
    bubbleTarget: enyo.Computed(function () {
        return this.get("controllerBubbleTarget");
    }, "controllerBubbleTarget")
});

refactor and simplify enyo.Controller base kind