import getURL from "discourse-common/lib/get-url";
import I18n from "I18n";
import { later, schedule } from "@ember/runloop";
import Component from "@ember/component";
import { iconHTML } from "discourse-common/lib/icon-library";
import discourseComputed, { on } from "discourse-common/utils/decorators";

/*global Resumable:true */

/**
  Example usage:

    {{resumable-upload
        target="/admin/backups/upload"
        success=(action "successAction")
        error=(action "errorAction")
        uploadText="UPLOAD"
    }}
**/
export default Component.extend({
  tagName: "button",
  classNames: ["btn", "ru"],
  classNameBindings: ["isUploading"],
  attributeBindings: ["translatedTitle:title"],
  resumable: null,
  isUploading: false,
  progress: 0,
  rerenderTriggers: ["isUploading", "progress"],
  uploadingIcon: null,
  progressBar: null,

  @on("init")
  _initialize() {
    this.resumable = new Resumable({
      target: getURL(this.target),
      maxFiles: 1, // only 1 file at a time
      headers: {
        "X-CSRF-Token": document.querySelector("meta[name='csrf-token']")
          .content
      }
    });

    this.resumable.on("fileAdded", () => {
      // automatically upload the selected file
      this.resumable.upload();

      // mark as uploading
      later(() => {
        this.set("isUploading", true);
        this._updateIcon();
      });
    });

    this.resumable.on("fileProgress", file => {
      // update progress
      later(() => {
        this.set("progress", parseInt(file.progress() * 100, 10));
        this._updateProgressBar();
      });
    });

    this.resumable.on("fileSuccess", file => {
      later(() => {
        // mark as not uploading anymore
        this._reset();

        // fire an event to allow the parent route to reload its model
        this.success(file.fileName);
      });
    });

    this.resumable.on("fileError", (file, message) => {
      later(() => {
        // mark as not uploading anymore
        this._reset();

        // fire an event to allow the parent route to display the error message
        this.error(file.fileName, message);
      });
    });
  },

  @on("didInsertElement")
  _assignBrowse() {
    schedule("afterRender", () => this.resumable.assignBrowse($(this.element)));
  },

  @on("willDestroyElement")
  _teardown() {
    if (this.resumable) {
      this.resumable.cancel();
      this.resumable = null;
    }
  },

  @discourseComputed("title", "text")
  translatedTitle(title, text) {
    return title ? I18n.t(title) : text;
  },

  @discourseComputed("isUploading", "progress")
  text(isUploading, progress) {
    if (isUploading) {
      return progress + " %";
    } else {
      return this.uploadText;
    }
  },

  didReceiveAttrs() {
    this._super(...arguments);
    this._updateIcon();
  },

  click() {
    if (this.isUploading) {
      this.resumable.cancel();
      later(() => this._reset());
      return false;
    } else {
      return true;
    }
  },

  _updateIcon() {
    const icon = this.isUploading ? "times" : "upload";
    this.set("uploadingIcon", `${iconHTML(icon)}`.htmlSafe());
  },

  _updateProgressBar() {
    const pb = `${"width:" + this.progress + "%"}`.htmlSafe();
    this.set("progressBar", pb);
  },

  _reset() {
    this.setProperties({ isUploading: false, progress: 0 });
    this._updateIcon();
    this._updateProgressBar();
  }
});
