import Evented from '@ember/object/evented';
import EmberObject, { set } from '@ember/object';
import { cancel, later } from '@ember/runloop';
import { guidFor } from '../utils/computed';

export default class Object extends EmberObject.extend(Evented) {
  exitTimer = null;
  exiting = false;
  isExitable = true;
  initializedTime = null;

  @(guidFor('message').readOnly())
  _guid;

  init() {
    super.init(...arguments);

    if (this.sticky) {
      return;
    }
    this.timerTask();
    this._setInitializedTime();
  }

  destroyMessage() {
    this._cancelTimer();
    if (this.exitTaskInstance) {
      cancel(this.exitTaskInstance);
      this._teardown();
    } else {
      this.exitTimerTask();
    }
  }

  exitMessage() {
    if (!this.isExitable) {
      return;
    }
    this.exitTimerTask();
    this.trigger('didExitMessage');
  }

  willDestroy() {
    if (this.onDestroy) {
      this.onDestroy();
    }

    this._cancelTimer();
    this._cancelTimer('exitTaskInstance');
    super.willDestroy(...arguments);
  }

  preventExit() {
    set(this, 'isExitable', false);
  }

  allowExit() {
    set(this, 'isExitable', true);
    this._checkIfShouldExit();
  }

  timerTask() {
    if (!this.timeout) {
      return;
    }
    const timerTaskInstance = later(() => {
      this.exitMessage();
    }, this.timeout);
    set(this, 'timerTaskInstance', timerTaskInstance);
  }

  exitTimerTask() {
    if (this.isDestroyed) {
      return;
    }
    set(this, 'exiting', true);
    if (this.extendedTimeout) {
      let exitTaskInstance = later(() => {
        this._teardown();
      }, this.extendedTimeout);
      set(this, 'exitTaskInstance', exitTaskInstance);
    } else {
      this._teardown();
    }
  }

  _setInitializedTime() {
    let currentTime = new Date().getTime();
    set(this, 'initializedTime', currentTime);

    return this.initializedTime;
  }

  _getElapsedTime() {
    let currentTime = new Date().getTime();

    return currentTime - this.initializedTime;
  }

  _cancelTimer(taskName = 'timerTaskInstance') {
    if (this[taskName]) {
      cancel(this[taskName]);
    }
  }

  _checkIfShouldExit() {
    if (this._getElapsedTime() >= this.timeout && !this.sticky) {
      this._cancelTimer();
      this.exitMessage();
    }
  }

  _teardown() {
    const queue = this.flashService?.queue;
    if (queue) {
      queue.removeObject(this);
    }
    this.destroy();
    this.trigger('didDestroyMessage');
  }
}

@@ -182,16 +182,147 @@
 uted';%0A%0A
+// Note:%0A// To avoid https://github.com/poteto/ember-cli-flash/issues/341 from happening, this class can't simply be called Object%0A
 export d
@@ -334,16 +334,21 @@
 t class 
+Flash
 Object e

rename flash Object class to FlashObject to avoid transpilation issues (#342)