'use strict';

class Notice {
  constructor(stateValue, messageValue, task) {
    this.stateValue = stateValue;
    this.messageValue = messageValue;
    this.task = task;
    this.listeners = [];
    switch (stateValue) {
      case "delayed":
        this.timer = window.setTimeout(() => this.execute(), 5000);
        break;
      case "executing":
        this.execute();
        break;
      case "success":
      case "warning":
      case "failed":
        this.startCloseTimer();
        break;
    }
  }
  get state() {
    return this.stateValue;
  }
  set state(value) {
    if (this.stateValue != value) {
      this.stateValue = value;
      this.emit();
    }
  }
  get message() {
    return this.messageValue;
  }
  set message(value) {
    if (this.messageValue != value) {
      this.messageValue = value;
      this.emit();
    }
  }
  listen(listener) {
    this.listeners.push(listener);
  }
  unlisten(listener) {
    this.listeners.filter(l => l != listener);
  }
  emit() {
    this.listeners.forEach(l => l(this));
  }
  execute() {
    this.clearTimer();
    if (this.task) {
      this.state = "executing";
      this.task(this).then(r => {
        this.messageValue = r[1];
        this.state = r[0] ? "success" : "failed";
        this.startCloseTimer();
      });
    }
    else
      this.state = "failed";
  }
  startCloseTimer() {
    this.timer = window.setTimeout(() => this.close(), 15000);
  }
  close() {
    this.clearTimer();
    this.state = "closed";
  }
  clearTimer() {
    if (this.timer) {
      window.clearTimeout(this.timer);
      this.timer = undefined;
    }
  }
  static delay(message, task) {
    return new Notice("delayed", message, task);
  }
  static execute(message, task) {
    return new Notice("executing", message, task);
  }
  static succeded(message) {
    return new Notice("success", message);
  }
  static failed(message) {
    return new Notice("failed", message);
  }
  static warn(message) {
    return new Notice("warning", message);
  }
}

exports.Notice = Notice;
