/**
@module ember
@submodule ember-runtime
*/

import { ENV } from 'ember-environment';
import {
  computed,
  observer
} from 'ember-metal';
import { assert, deprecateFunc } from 'ember-debug';

const a_slice = Array.prototype.slice;
const FunctionPrototype = Function.prototype;

if (ENV.EXTEND_PROTOTYPES.Function) {
  /**
    The `property` extension of Javascript's Function prototype is available
    when `EmberENV.EXTEND_PROTOTYPES` or `EmberENV.EXTEND_PROTOTYPES.Function` is
    `true`, which is the default.

    Computed properties allow you to treat a function like a property:

    ```javascript
    MyApp.President = Ember.Object.extend({
      firstName: '',
      lastName:  '',

      fullName: function() {
        return this.get('firstName') + ' ' + this.get('lastName');
      }.property() // Call this flag to mark the function as a property
    });

    let president = MyApp.President.create({
      firstName: 'Barack',
      lastName: 'Obama'
    });

    president.get('fullName'); // 'Barack Obama'
    ```

    Treating a function like a property is useful because they can work with
    bindings, just like any other property.

    Many computed properties have dependencies on other properties. For
    example, in the above example, the `fullName` property depends on
    `firstName` and `lastName` to determine its value. You can tell Ember
    about these dependencies like this:

    ```javascript
    MyApp.President = Ember.Object.extend({
      firstName: '',
      lastName:  '',

      fullName: function() {
        return this.get('firstName') + ' ' + this.get('lastName');

        // Tell Ember.js that this computed property depends on firstName
        // and lastName
      }.property('firstName', 'lastName')
    });
    ```

    Make sure you list these dependencies so Ember knows when to update
    bindings that connect to a computed property. Changing a dependency
    will not immediately trigger an update of the computed property, but
    will instead clear the cache so that it is updated when the next `get`
    is called on the property.

    See [Ember.ComputedProperty](/api/classes/Ember.ComputedProperty.html), [Ember.computed](/api/classes/Ember.computed.html).

    @method property
    @for Function
    @public
  */
  FunctionPrototype.property = function () {
    let ret = computed(this);
    // ComputedProperty.prototype.property expands properties; no need for us to
    // do so here.
    return ret.property(...arguments);
  };

  /**
    The `observes` extension of Javascript's Function prototype is available
    when `EmberENV.EXTEND_PROTOTYPES` or `EmberENV.EXTEND_PROTOTYPES.Function` is
    true, which is the default.

    You can observe property changes simply by adding the `observes`
    call to the end of your method declarations in classes that you write.
    For example:

    ```javascript
    Ember.Object.extend({
      valueObserver: function() {
        // Executes whenever the "value" property changes
      }.observes('value')
    });
    ```

    In the future this method may become asynchronous.

    See `Ember.observer`.

    @method observes
    @for Function
    @public
  */
  FunctionPrototype.observes = function(...args) {
    args.push(this);
    return observer.apply(this, args);
  };


  FunctionPrototype._observesImmediately = function () {
    assert(
      'Immediate observers must observe internal properties only, ' +
      'not properties on other objects.',
      function checkIsInternalProperty() {
        for (let i = 0; i < arguments.length; i++) {
          if (arguments[i].indexOf('.') !== -1) {
            return false;
          }
        }
        return true;
      }
    );

    // observes handles property expansion
    return this.observes(...arguments);
  };
  /**
    The `observesImmediately` extension of Javascript's Function prototype is
    available when `EmberENV.EXTEND_PROTOTYPES` or
    `EmberENV.EXTEND_PROTOTYPES.Function` is true, which is the default.

    You can observe property changes simply by adding the `observesImmediately`
    call to the end of your method declarations in classes that you write.
    For example:

    ```javascript
    Ember.Object.extend({
      valueObserver: function() {
        // Executes immediately after the "value" property changes
      }.observesImmediately('value')
    });
    ```

    In the future, `observes` may become asynchronous. In this event,
    `observesImmediately` will maintain the synchronous behavior.

    See `Ember.immediateObserver`.

    @method observesImmediately
    @for Function
    @deprecated
    @private
  */
  FunctionPrototype.observesImmediately = deprecateFunc(
    'Function#observesImmediately is deprecated. Use Function#observes instead',
    { id: 'ember-runtime.ext-function', until: '3.0.0' },
    FunctionPrototype._observesImmediately
  );

  /**
    The `on` extension of Javascript's Function prototype is available
    when `EmberENV.EXTEND_PROTOTYPES` or `EmberENV.EXTEND_PROTOTYPES.Function` is
    true, which is the default.

    You can listen for events simply by adding the `on` call to the end of
    your method declarations in classes or mixins that you write. For example:

    ```javascript
    Ember.Mixin.create({
      doSomethingWithElement: function() {
        // Executes whenever the "didInsertElement" event fires
      }.on('didInsertElement')
    });
    ```

    See `Ember.on`.

    @method on
    @for Function
    @public
  */
  FunctionPrototype.on = function () {
    let events = a_slice.call(arguments);
    this.__ember_listens__ = events;

    return this;
  };
}

@@ -90,16 +90,22 @@
 mport %7B%0A
+  on,%0A
   comput
@@ -108,16 +108,16 @@
 mputed,%0A
-
   observ
@@ -199,47 +199,8 @@
 ';%0A%0A
-const a_slice = Array.prototype.slice;%0A
 cons
@@ -2297,157 +2297,23 @@
     
-let ret = computed(this);%0A    // ComputedProperty.prototype.property expands properties; no need for us to%0A    // do so here.%0A    return ret.property
+return computed
 (...
@@ -2313,32 +2313,38 @@
 ted(...arguments
+, this
 );%0A  %7D;%0A%0A  /**%0A 
@@ -3058,23 +3058,16 @@
 ion(
-...args
 ) %7B%0A    
 args
@@ -3066,60 +3066,41 @@
     
-args.push(this);%0A    return observer.apply(this, arg
+return observer(...arguments, thi
 s);%0A
@@ -5352,99 +5352,37 @@
     
-let events = a_slice.call(arguments);%0A    this.__ember_listens__ = events;%0A%0A    return
+return on(...arguments,
  this
+)
 ;%0A  

correct function extensions