<!--
@license
Copyright (c) 2015 Winston Howes. All rights reserved.
This code may only be used under the MIT license found at https://github.com/winhowes/file-upload/blob/master/LICENSE
-->
<link rel="import" href="../../bower_components/polymer/polymer.html">

<!--
An element providing a solution to no problem in particular.

Example:

    <file-upload target="/path/to/destination"></file-upload>

@demo
-->

<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-progress/paper-progress.html">
<link rel="import" href="../../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../../bower_components/iron-signals/iron-signals.html">

<dom-module id="file-upload">

  <style type="text/css">
    :host {
        display: inline-block;
    }

    .enabled {
      border: 1px dashed #555;
      @apply(--file-upload-upload-border-enabled);
    }

    .hover {
      opacity: .7;
      border: 1px dashed #111;
      @apply(--file-upload-upload-border-hover);
    }

    .file{
      width: 100%;
    }
    .name{
      width: 100%;
    }


    #UploadBorder{
      vertical-align: middle;
      color: #555;
      padding: 20px;
      max-height: 300px;
      overflow-y: auto;
      display: inline-block;
      @apply(--file-upload-upload-border);
    }

    #dropArea {
      text-align: center;
      @apply(--file-upload-drop-area);
    }

    paper-button#button {
      margin-bottom: 20px;
      @apply(--file-upload-button);
    }

    .file {
      padding: 10px 0px;
      @apply(--file-upload-file);
    }

    .commands {
      float: right;
      @apply(--file-upload-commands);
    }

    .commands iron-icon:not([icon="check-circle"]) {
      cursor: pointer;
      opacity: .9;
      @apply(--file-upload-commands-faded);
    }

    .commands iron-icon:hover {
      opacity: 1;
      @apply(--file-upload-commands-hovered);
    }

    [hidden] {
      display: none;
    }

    .error {
      color: #f40303;
      font-size: 11px;
      margin: 2px 0px -3px;
      @apply(--file-upload-error);
    }

    paper-progress {
      --paper-progress-active-color: #03a9f4;
    }

    paper-progress[error] {
      --paper-progress-active-color: #f40303;
    }

    paper-button#button {
      margin-bottom: 20px;
      background-color: aquamarine;
    }
  </style>

  <template>
    <div>
      <paper-button id="button" icon="file-upload" class="blue" on-click="_fileClick">
        <content></content>
      </paper-button>
      <div id='UploadBorder'>
        <div id="dropArea" hidden$="{{!_shownDropText}}">{{droptext}}</div>
        <template is="dom-repeat" items="{{files}}">
          <div class="file">
            <div class="name">
              <span>{{item.name}}</span>
              <div class="commands">
                <iron-icon icon="autorenew" title="{{retryText}}" on-click="_retryUpload" hidden$="{{!item.error}}"></iron-icon>
                <iron-icon icon="cancel" title="{{removeText}}" on-click="_cancelUpload" hidden$="{{item.complete}}"></iron-icon>
                <iron-icon icon="check-circle" title="{{successText}}" hidden$="{{!item.complete}}"></iron-icon>
              </div>
            </div>
            <div class="error" hidden$="{{!item.error}}">{{errorText}}</div>
            <div hidden$={{progressHidden}}>
              <paper-progress value$="{{item.progress}}" error$="{{item.error}}"></paper-progress>
            </div>
          </div>
        </template>
      </div>
    </div>
    <input type="file" id="fileInput" on-change="_fileChange" hidden multiple="{{multi}}" accept="{{accept}}">
    <!--<paper-toast id="toastSuccess" text="File uploaded successfully!"></paper-toast>
    <paper-toast id="toastFail" text="Error uploading file!"></paper-toast>-->
  </template>

</dom-module>

<script>

  Polymer({

    is: 'file-upload',

     /**
      * Fired when a response is received status code 200.
      *
      * @event success
    */
     /**
      * Fired when a response is received other status code.
      *
      * @event error
    */
    /**
     * Fired when a file is about to be uploaded.
     *
     * @event before-upload
   */

    properties: {

      /**
       * `target` is the target url to upload the files to.
       * Additionally by adding "<name>" in your url, it will be replaced by
       * the file name.
       */
      target: {
        type: String,
        value: ""
      },

      /**
       * `accept` is the set of comma separated file extensions or mime types
       * to filter as accepted.
      */

      accept: {
        type: String,
        value: ""
      },

      /**
       * `progressHidden` indicates whether or not the progress bar should be hidden.
       */
      progressHidden: {
        type: Boolean,
        value: false
      },

      /**
       * `droppable` indicates whether or not to allow file drop.
      */
      droppable: {
        type: Boolean,
        value: false,
        observer: 'init'
      },

      /**
       * `droptext` is the  text to display in the file drop area.
      */
      droptext: {
        type: String,
        value: "Drop Files Here"
      },

      /**
       * `multi` indicates whether or not to allow multiple files to be uploaded.
      */
      multi: {
        type: Boolean,
        value: false
      },

      /**
       * `files` is the list of files to be uploaded
      */
      files: {
        type: Array,
        value: function() {
            return [];
        }
      },

      /**
       * `method` is the http method to be used during upload
      */
      method: {
        type: String,
        value: "POST"
      },

      /**
       * `raised` indicates whether or not the button should be raised
      */
      raised: {
        type: Boolean,
        value: false
      },

      /**
       * `noink` indicates that the button should not have an ink effect
      */
      noink: {
        type: Boolean,
        value: false
      },

      /**
       * `headers` is a key value map of header names and values
      */
      headers: {
        type: Object,
        value: {},
      },

      /**
       * `retryText` is the text for the tooltip to retry an upload
      */
      retryText: {
        type: String,
        value: 'Retry Upload'
      },

      /**
       * `removeText` is the text for the tooltip to remove an upload
      */
      removeText: {
          type: String,
          value: 'Remove'
      },

      /**
       * `successText` is the text for the tooltip of a successful upload
      */
      successText: {
          type: String,
          value: 'Success'
      },

      /**
       * `errorText` is the text to display for a failed upload
      */
      errorText: {
          type: String,
          value: 'Error uploading file...'
      },

      /**
       * `_shownDropText` indicates whether or not the drop text should be shown
      */
      _shownDropText: {
        type: Boolean,
        value: false
      },

      site: {
        type: String,
        value: 'swsdp'
      },

      container: {
        type: String,
        value: 'documentLibrary'
      },
    },

    /**
     * Clears the list of files
    */
    clear: function() {
      this.set("files", []);
      this._showDropText();
    },

    ready: function() {
    },

    init: function() {
      if (this.raised) {
        this.toggleAttribute("raised", true, this.$.button);
      }
      if (this.noink) {
        this.toggleAttribute("noink", true, this.$.button);
      }

      if (this.droppable === 'true') {
        this._showDropText();
        this.setupDrop();
      } else { this._hideDropText(); }
    },

    /**
     * A function to set up a drop area for drag-and-drop file uploads
    */
    setupDrop: function() {
      var uploadBorder = this.$.UploadBorder;
      this.toggleClass("enabled", true, uploadBorder);

      this.ondragover = function(e) {
        e.stopPropagation();
        this.toggleClass("hover", true, uploadBorder);
        return false;
      }

      this.ondragleave = function() {
        this.toggleClass("hover", false, uploadBorder);
        return false;
      }

      this.ondrop = function(event) {
        this.toggleClass("hover", false, uploadBorder);
        event.preventDefault();
        var length = event.dataTransfer.files.length;
        for (var i = 0; i < length; i++) {
          var file = event.dataTransfer.files[i];

          // Check if multiple upload is allowed
          if (!this.multi && this.files.length !== 0) {
            return;
          }

          // Check if filetype is accepted
          var mimeType = ((file.type !== '') ? file.type.match(/^[^\/]*\//)[0] : null);
          var fileType = file.name.match(/\.[^\.]*$/)[0];
          if (this.accept !== '' && !(this.accept.indexOf(mimeType) > -1 || this.accept.indexOf(fileType) > -1)) {
            return;
          }

          file.progress = 0;
          file.error = false;
          file.complete = false;
          this.push("files", file);
          this.uploadFile(file);
        }
      }
    },

    /**
     * Clicks the invisible file input
    */
    _fileClick: function() {
      var elem = this.$.fileInput;
      if (elem && document.createEvent) { // sanity check
        var evt = document.createEvent("MouseEvents");
        evt.initEvent("click", true, false);
        elem.dispatchEvent(evt);
      }
    },

    /**
     * Called whenever the list of selected files changes
    */
    _fileChange: function(e) {
      var length = e.target.files.length;
      for (var i = 0; i < length; i++) {
        var file = e.target.files[i];
        file.progress = 0;
        file.error = false;
        file.complete = false;
        this.push("files", file);
        this.uploadFile(file);
      }
    },

    /**
     * Cancels the file upload for a specific file
     *
     * @param {object} a file, an element of the files array
    */
    cancel: function(file) {
      if (file && file.xhr) {
        file.xhr.abort();
        this.splice("files", this.files.indexOf(file), 1);
        this._showDropText();
      }
    },

    /**
     * Cancels the file upload
     *
     * @param {object}, an event object
    */
    _cancelUpload: function(e) {
      this.cancel(e.model.__data__.item);
    },

    /**
     * Retries to upload the file
     *
     * @param {object}, an event object
    */
    _retryUpload: function(e) {
      e.model.set("item.error", false);
      e.model.set("item.progress", 0);
      // The async helps give visual feedback of a retry occurring, even though it's less efficient.
      var self = this;
      this.async(function() {
        self.uploadFile(e.model.__data__.item);
      }, 50);
    },

    /**
     * Whether or not to display the drop text
    */
    _showDropText: function() {
      this.set("_shownDropText", true);
    },

    _hideDropText: function() {
      this.set("_shownDropText", false);
      var uploadBorder = this.$.UploadBorder;
      this.toggleClass("enabled", false, uploadBorder);
      this.toggleClass("hover", false, uploadBorder);
    },

    /**
     * Uploads a file
     *
     * @param {object} a file, an element of the files array
    */
    uploadFile: function(file) {
      if (!file) {
        return;
      }
      this.fire('before-upload');
      this._showDropText();
      var prefix = "files." + this.files.indexOf(file);
      var self = this;

      var formData = new FormData();
      formData.append("filedata", file, file.name);
      formData.append('siteid',   this.site);
      formData.append('containerid', this.container);

      var xhr = file.xhr = new XMLHttpRequest();

      xhr.upload.onprogress = function(e) {
        var done = e.loaded, total = e.total;
        self.set(prefix + ".progress", Math.floor((done/total)*1000)/10);
      };

      var url = this.target.replace("<name>", file.name);
      xhr.open(this.method, url, true);

      for (key in this.headers) {
        if (this.headers.hasOwnProperty(key)) {
          xhr.setRequestHeader(key, this.headers[key]);
        }
      }
      xhr.setRequestHeader("Authorization", 'Basic ' + btoa('admin:admin'))

      xhr.onload = function(e) {
        if (xhr.status === 200) {
          self.fire("success", {xhr: xhr});
          self.set(prefix + ".complete", true);
          if(document.querySelector("#alfresco-app")) {
            document.querySelector('#alfresco-app').fire('iron-signal', {name: "uploaded", data: "uploaded!"});
          }
        } else {
          self.set(prefix + ".error", true);
          self.set(prefix + ".complete", false);
          self.set(prefix + ".progress", 100);
          self.updateStyles();
          self.fire("error", {xhr:xhr});
        }
      };
      xhr.send(formData);
    }
  });

</script>