import * as toastr from "toastr";

export enum NotificationPositionEnum {
  TopLeft = 1,
  TopRight = 2,
  BottomLeft = 3,
  BottomRight = 4
}

export class NotificationModule {

  public static timeout: number;
  public static errorTimeout: number;
  public static extendedTimeout: number;
  public static position: NotificationPositionEnum = NotificationPositionEnum.TopRight;
  public static newestOnTop: boolean = false;

  public static showWarning(title: string, message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    this.setOptions(autohide);

    title = this.setTitleHtml(title);
    message = this.setMessageWithActionsHtml(message, NotificationType.Warning, actionsHtml);

    toastr.warning(message, title, {
      iconClass: " "
    });
  }

  public static showWarningSmall(message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    this.setOptions(autohide);
    this.setSmall();

    message = this.setMessageWithActionsHtml(message, NotificationType.Warning, actionsHtml);

    toastr.warning(message, "", {
      iconClass: " "
    });
  }

  public static showInfo(title: string, message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    title = this.setTitleHtml(title);
    message = this.setMessageWithActionsHtml(message, NotificationType.Info, actionsHtml);

    this.setOptions(autohide);
    toastr.info(message, title);
  }

  public static showInfoSmall(message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    this.setOptions(autohide);
    this.setSmall();

    message = this.setMessageWithActionsHtml(message, NotificationType.Info, actionsHtml);

    toastr.info(message);
  }

  public static showError(title: string, message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    this.setOptions(autohide, true);

    title = this.setTitleHtml(title);
    message = this.setMessageWithActionsHtml(message, NotificationType.Error, actionsHtml);

    toastr.error(message, title);
  }

  public static showErrorSmall(message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    this.setOptions(autohide, true);
    this.setSmall();

    message = this.setMessageWithActionsHtml(message, NotificationType.Error, actionsHtml);

    toastr.error(message);
  }

  public static showSuccess(title: string, message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    this.setOptions(autohide);

    title = this.setTitleHtml(title);
    message = this.setMessageWithActionsHtml(message, NotificationType.Success, actionsHtml);

    toastr.success(message, title);
  }

  public static showSuccessSmall(message: string, actionsHtml?: JQuery<HTMLElement>, autohide?: boolean) {

    if (autohide === undefined) {
      autohide = true;
    }

    this.setOptions(autohide);
    this.setSmall();

    message = this.setMessageWithActionsHtml(message, NotificationType.Success, actionsHtml);

    toastr.success(message);
  }

  private static setMessageWithActionsHtml(message: string, type: NotificationType, actionsHtml?: JQuery<HTMLElement>) {
    if (actionsHtml !== undefined && actionsHtml !== null && actionsHtml.length > 0) {
      message = message + $("<div>").append($("<div>").addClass("toast-actions").append(actionsHtml)).html();
    }

    const $icon = $("<div>").addClass("notification-icon").append(
      $("<svg class=\"embla-icon\" aria-hidden=\"true\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><use xlink:href=\"/dist/icons/sprite.symbol.svg#" + type.toString() + "\"></use></svg>")
    );

    return $("<div>").append($icon).html() + message;
  }

  private static setTitleHtml(title: string) {

    return $("<div>")
      .append(
        $("<h5>").text(title)
      ).html();
  }

  private static setOptions(autoHide?: boolean, isError?: boolean) {

    if (autoHide === undefined) {
      autoHide = true;
    }

    toastr.options.onShown = undefined;
    toastr.options.positionClass = this.getPositionClass();
    toastr.options.progressBar = false;
    toastr.options.closeButton = true;
    toastr.options.newestOnTop = this.newestOnTop;
    toastr.options.toastClass = "toast";

    if (autoHide === false) {
      toastr.options.timeOut = 0;
      toastr.options.extendedTimeOut = 3000;
    } else {

      let timeout = 3000;
      if (this.timeout !== undefined) {
        timeout = this.timeout;
      }

      if (isError === true) {

        timeout = 10000;
        if (this.errorTimeout !== undefined) {
          timeout = this.errorTimeout;
        }

      }

      let extendedTimeout = 3000;
      if (this.extendedTimeout !== undefined) {
        extendedTimeout = this.extendedTimeout;
      }

      toastr.options.timeOut = timeout;
      toastr.options.extendedTimeOut = extendedTimeout;
    }
  }

  private static setSmall() {
    toastr.options.toastClass += " notification-small";
  }

  private static getPositionClass(): string {
    switch (this.position) {
      case NotificationPositionEnum.TopLeft:
        return "toast-top-left";
        
      case NotificationPositionEnum.TopRight:
        return "toast-top-right";

      case NotificationPositionEnum.BottomLeft:
          return "toast-bottom-left";

      case NotificationPositionEnum.BottomRight:
          return "toast-bottom-right";
    }

    throw Error("Unknown position: " + this.position);
  }
}

enum NotificationType {
  Success = "success",
  Info = "info",
  Warning = "warning",
  Error = "danger"
}
