import { a as _applyDecoratedDescriptor, B as BaseObject, b as _initializerDefineProperty, _ as _defineProperty } from './base-object-HAEdWjmg.js';
import { typeOf } from './type-check.js';
import { RSVP } from './ember.js';
import { E as Evented } from './evented-BCTya3yE.js';

var _dec, _dec2, _dec3, _class2, _descriptor, _descriptor2, _descriptor3;
const dateComputed = function () {
  return function (target, propertyKey) {
    return {
      get() {
        return this[`__${propertyKey}__`];
      },
      set(date) {
        if (typeOf(date) === 'date') {
          this[`__${propertyKey}__`] = date;
          return;
        } else if (typeof date === 'number' || typeof date === 'string') {
          this[`__${propertyKey}__`] = new Date(date);
          return;
        }
        this[`__${propertyKey}__`] = null;
      }
    };
  };
};
let _class = (_dec = dateComputed(), _dec2 = dateComputed(), _dec3 = dateComputed(), _class2 = class _class2 extends BaseObject {
  constructor(...args) {
    super(...args);
    _initializerDefineProperty(this, "createdAt", _descriptor, this);
    _initializerDefineProperty(this, "settledAt", _descriptor2, this);
    _initializerDefineProperty(this, "chainedAt", _descriptor3, this);
    _defineProperty(this, "parent", null);
    _defineProperty(this, "children", []);
  }
  get level() {
    const parent = this.parent;
    if (!parent) {
      return 0;
    }
    return parent.level + 1;
  }
  get isSettled() {
    return this.isFulfilled || this.isRejected;
  }
  get isFulfilled() {
    return this.state === 'fulfilled';
  }
  get isRejected() {
    return this.state === 'rejected';
  }
}, _descriptor = _applyDecoratedDescriptor(_class2.prototype, "createdAt", [_dec], {
  configurable: true,
  enumerable: true,
  writable: true,
  initializer: null
}), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "settledAt", [_dec2], {
  configurable: true,
  enumerable: true,
  writable: true,
  initializer: null
}), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "chainedAt", [_dec3], {
  configurable: true,
  enumerable: true,
  writable: true,
  initializer: null
}), _class2);

var _PromiseAssembler;
class PromiseAssembler extends BaseObject {
  constructor(data) {
    super(data);
    // RSVP lib to debug
    _defineProperty(this, "isStarted", false);
    Evented.applyTo(this);
  }

  // eslint-disable-next-line ember/classic-decorator-hooks
  init() {
    super.init();
    this.all = [];
    this.promiseIndex = {};
  }
  start() {
    this.RSVP.configure('instrument', true);
    this.promiseChained = e => {
      chain.call(this, e);
    };
    this.promiseRejected = e => {
      reject.call(this, e);
    };
    this.promiseFulfilled = e => {
      fulfill.call(this, e);
    };
    this.promiseCreated = e => {
      create.bind(this)(e);
    };
    this.RSVP.on('chained', this.promiseChained);
    this.RSVP.on('rejected', this.promiseRejected);
    this.RSVP.on('fulfilled', this.promiseFulfilled);
    this.RSVP.on('created', this.promiseCreated);
    this.isStarted = true;
  }
  stop() {
    if (this.isStarted) {
      this.RSVP.configure('instrument', false);
      this.RSVP.off('chained', this.promiseChained);
      this.RSVP.off('rejected', this.promiseRejected);
      this.RSVP.off('fulfilled', this.promiseFulfilled);
      this.RSVP.off('created', this.promiseCreated);
      this.all.forEach(item => {
        item.destroy();
      });
      this.all = [];
      this.promiseIndex = {};
      this.promiseChained = null;
      this.promiseRejected = null;
      this.promiseFulfilled = null;
      this.promiseCreated = null;
      this.isStarted = false;
    }
  }
  willDestroy() {
    this.stop();
    super.willDestroy();
  }
  createPromise(props) {
    let promise = new _class(props);
    let index = this.all.length;
    this.all.push(promise);
    this.promiseIndex[promise.guid] = index;
    return promise;
  }
  find(guid) {
    if (guid) {
      const index = this.promiseIndex[guid];
      if (index !== undefined) {
        return this.all[index];
      }
    } else {
      return this.all;
    }
  }
  findOrCreate(guid) {
    return this.find(guid) || this.createPromise({
      guid
    });
  }
  updateOrCreate(guid, properties) {
    let entry = this.find(guid);
    if (entry) {
      Object.assign(entry, properties);
    } else {
      properties = Object.assign({}, properties);
      properties.guid = guid;
      entry = this.createPromise(properties);
    }
    return entry;
  }
}
_PromiseAssembler = PromiseAssembler;
_PromiseAssembler.prototype.RSVP = RSVP;
function fulfill(event) {
  const guid = event.guid;
  const promise = this.updateOrCreate(guid, {
    label: event.label,
    settledAt: event.timeStamp,
    state: 'fulfilled',
    value: event.detail
  });
  this.trigger('fulfilled', {
    promise
  });
}
function reject(event) {
  const guid = event.guid;
  const promise = this.updateOrCreate(guid, {
    label: event.label,
    settledAt: event.timeStamp,
    state: 'rejected',
    reason: event.detail
  });
  this.trigger('rejected', {
    promise
  });
}
function chain(event) {
  let guid = event.guid;
  let promise = this.updateOrCreate(guid, {
    label: event.label,
    chainedAt: event.timeStamp
  });
  let children = promise.children;
  let child = this.findOrCreate(event.childGuid);
  child.parent = promise;
  children.push(child);
  this.trigger('chained', {
    promise,
    child
  });
}
function create(event) {
  const guid = event.guid;
  const promise = this.updateOrCreate(guid, {
    label: event.label,
    createdAt: event.timeStamp,
    stack: event.stack
  });

  // todo fix ordering
  if (!promise.state) {
    promise.state = 'created';
  }
  this.trigger('created', {
    promise
  });
}

export { PromiseAssembler as default };
