(function (factory) {
  "use strict";
  require(["AbilianWidget", "jquery", "bootbox"], factory);
})(function (Abilian, $, bootbox) {
  "use strict";

  function TaskProgress(node, options) {
    this.state = "PENDING";
    this.taskId = options.taskId;
    this.indexUrl = options.indexUrl;
    this.node = node;
    this.progressBar = node.find(".progress-bar");
    this.intervalId = window.setInterval(this.doRequest.bind(this), 500);
  }

  TaskProgress.prototype.doRequest = function () {
    $.ajax({
      url: Abilian.api.crm.excel.taskStatusUrl,
      data: { task_id: this.taskId },
      dataType: "json",
      timeout: 450,
      cache: false,
      success: this.ajaxSuccess.bind(this),
    });
  };

  TaskProgress.prototype.stopPolling = function () {
    window.clearInterval(this.intervalId);
  };

  TaskProgress.prototype.ajaxSuccess = function (data, status, xhr) {
    var taskState = data.state;

    switch (taskState) {
      case "PROGRESS":
        this.updateProgress(data);
        break;
      case "SUCCESS":
        this.updateFinished(data);
        break;
      case "PENDING":
      case "STARTED":
        break;
      case "FAILURE":
        this.stopPolling();
        this.notifyFailure(data);
        break;
      case "REVOKED":
        this.stopPolling();
      // this.redirectToIndex
    }
    this.state = data.state;
  };

  TaskProgress.prototype.start = function (data) {
    this.node.removeClass("progress-bar-striped");
    this.progressBar.width("0%");
    this.progressBar.text("0%");
  };

  TaskProgress.prototype.updateProgress = function (data) {
    if (data.state != this.state) {
      this.start();
    }
    var exported = data.exported;
    var total = data.total;
    var percent = Math.min(Math.round((exported / total) * 100), 100);

    this.progressBar.attr("aria-valuenow", percent);
    percent = percent.toString() + "%";
    this.progressBar.width(percent);
    this.progressBar.text(percent);
  };

  TaskProgress.prototype.updateFinished = function (data) {
    this.stopPolling();
    this.progressBar.attr("aria-valuenow", 100);
    this.progressBar.width("100%");
    this.progressBar.text("100%");

    var indexUrl = this.indexUrl;
    var filename = data.filename;
    var downloadUrl = data.downloadUrl;
    var downloadBtn = this.node.parent().find(".download-btn a");
    var filenameWrapper = downloadBtn.find(".filename");

    downloadBtn.attr("href", downloadUrl);
    filenameWrapper.text(filename);
    downloadBtn.parent().removeClass("hide");

    downloadBtn.on("click", function () {
      window.setTimeout(function () {
        window.location = indexUrl;
      }, 500);
    });

    //        window.open(downloadUrl);
    //        window.location = this.indexUrl;
    //        window.focus();
  };

  TaskProgress.prototype.notifyFailure = function (data) {
    var indexUrl = this.indexUrl;
    var message = $("<p></p>")
      .addClass("text-warning")
      .append($("<i></i>").addClass("fa fa-exclamation-triangle"))
      .append(data.message);

    function redirectToIndex() {
      window.location = indexUrl;
    }

    bootbox.alert({
      message: message.html(),
      callback: redirectToIndex,
      // locale: Abilian.i18n...
    });
  };

  function initTaskProgress(params) {
    var taskId = this.data("taskId");
    var indexUrl = this.data("indexUrl");
    return new TaskProgress(this, { taskId: taskId, indexUrl: indexUrl });
  }

  Abilian.registerWidgetCreator("crmExcelExport", initTaskProgress);
});
