import './index.js';
import Mixin from './mixin.js';
import { c as computed, g as get } from '../../shared-chunks/cache-DtDz7X5V.js';
import '../-internals/meta/lib/meta.js';
import '../debug/index.js';
import '../../@glimmer/validator/index.js';
import '../../shared-chunks/mandatory-setter-CXNsxygN.js';
import '@embroider/macros';
import '../../@glimmer/destroyable/index.js';
import '../../@glimmer/manager/index.js';
import { s as setProperties } from '../../shared-chunks/set_properties-D2_u0phU.js';
import '../../shared-chunks/env-DxZ20QzS.js';

/**
  @module @ember/object/promise-proxy-mixin
*/

function tap(proxy, promise) {
  setProperties(proxy, {
    isFulfilled: false,
    isRejected: false
  });
  return promise.then(value => {
    if (!proxy.isDestroyed && !proxy.isDestroying) {
      setProperties(proxy, {
        content: value,
        isFulfilled: true
      });
    }
    return value;
  }, reason => {
    if (!proxy.isDestroyed && !proxy.isDestroying) {
      setProperties(proxy, {
        reason,
        isRejected: true
      });
    }
    throw reason;
  }, 'Ember: PromiseProxy');
}

/**
  A low level mixin making ObjectProxy promise-aware.

  ```javascript
  import { resolve } from 'rsvp';
  import $ from 'jquery';
  import ObjectProxy from '@ember/object/proxy';
  import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';

  let ObjectPromiseProxy = ObjectProxy.extend(PromiseProxyMixin);

  let proxy = ObjectPromiseProxy.create({
    promise: resolve($.getJSON('/some/remote/data.json'))
  });

  proxy.then(function(json){
     // the json
  }, function(reason) {
     // the reason why you have no json
  });
  ```

  the proxy has bindable attributes which
  track the promises life cycle

  ```javascript
  proxy.get('isPending')   //=> true
  proxy.get('isSettled')  //=> false
  proxy.get('isRejected')  //=> false
  proxy.get('isFulfilled') //=> false
  ```

  When the $.getJSON completes, and the promise is fulfilled
  with json, the life cycle attributes will update accordingly.
  Note that $.getJSON doesn't return an ECMA specified promise,
  it is useful to wrap this with an `RSVP.resolve` so that it behaves
  as a spec compliant promise.

  ```javascript
  proxy.get('isPending')   //=> false
  proxy.get('isSettled')   //=> true
  proxy.get('isRejected')  //=> false
  proxy.get('isFulfilled') //=> true
  ```

  As the proxy is an ObjectProxy, and the json now its content,
  all the json properties will be available directly from the proxy.

  ```javascript
  // Assuming the following json:
  {
    firstName: 'Stefan',
    lastName: 'Penner'
  }

  // both properties will accessible on the proxy
  proxy.get('firstName') //=> 'Stefan'
  proxy.get('lastName')  //=> 'Penner'
  ```

  @class PromiseProxyMixin
  @public
*/

const PromiseProxyMixin = Mixin.create({
  reason: null,
  isPending: computed('isSettled', function () {
    return !get(this, 'isSettled');
  }).readOnly(),
  isSettled: computed('isRejected', 'isFulfilled', function () {
    return get(this, 'isRejected') || get(this, 'isFulfilled');
  }).readOnly(),
  isRejected: false,
  isFulfilled: false,
  promise: computed({
    get() {
      throw new Error("PromiseProxy's promise must be set");
    },
    set(_key, promise) {
      return tap(this, promise);
    }
  }),
  then: promiseAlias('then'),
  catch: promiseAlias('catch'),
  finally: promiseAlias('finally')
});
function promiseAlias(name) {
  return function (...args) {
    let promise = get(this, 'promise');

    // We need this cast because `Parameters` is deferred so that it is not
    // possible for TS to see it will always produce the right type. However,
    // since `AnyFn` has a rest type, it is allowed. See discussion on [this
    // issue](https://github.com/microsoft/TypeScript/issues/47615).
    return promise[name](...args);
  };
}

export { PromiseProxyMixin as default };
