function delegateService(methodNames) {
  return ['$log', function($log) {
    var delegate = this;

    var instances = this._instances = [];
    this._registerInstance = function(instance, handle) {
      handle || (handle = ionic.Utils.nextUid());

      instance.$$delegateHandle = handle;
      instances.push(instance);

      return function deregister() {
        var index = instances.indexOf(instance);
        if (index !== -1) {
          instances.splice(index, 1);
        }
      };
    };

    this.forHandle = function(handle) {
      if (!handle) {
        return delegate;
      }
      return new InstanceForHandle(handle);
    };

    /*
     * Creates a new object that will have all the methodNames given,
     * and call them on the given the controller instance matching given
     * handle.
     * The reason we don't just let forHandle return the controller instance
     * itself is that the controller instance might not exist yet.
     *
     * We want people to be able to do
     * `var instance = $ionicScrollDelegate.forHandle('foo')` on controller
     * instantiation, but on controller instantiation a child directive
     * may not have been compiled yet!
     *
     * So this is our way of solving this problem: we create an object
     * that will only try to fetch the controller with given handle
     * once the methods are actually called.
     */
    function InstanceForHandle(handle) {
      this.handle = handle;
    }
    methodNames.forEach(function(methodName) {
      InstanceForHandle.prototype[methodName] = function() {
        var handle = this.handle;
        var instancesToUse = instances.filter(function(instance) {
          return instance.$$delegateHandle === handle;
        });
        if (!instancesToUse.length) {
          return $log.warn(
            'Delegate for handle "'+this.handle+'" could not find a',
            'corresponding element with delegate-handle="'+this.handle+'"!',
            methodName, 'was not called!');
        }
        return callMethod(instancesToUse, methodName, arguments);
      };
      delegate[methodName] = function() {
        return callMethod(instances, methodName, arguments);
      };

      function callMethod(instancesToUse, methodName, args) {
        var finalResult;
        var result;
        instancesToUse.forEach(function(instance) {
          result = instance[methodName].apply(instance, args);
          if (!angular.isDefined(finalResult)) {
            finalResult = result;
          }
        });
        return finalResult;
      }
    });
  }];
}
@ngdoc module
@name ionic
@description
Ionic main module.