(function(global) {
  'use strict';
  // Copy from clipboard
  global.copyFromClipboard = (function() {
    var UPLOADED_IMAGE = {};
    var LOCATION = '';
    function init(location) {
      LOCATION = location;
      global.addEventListener('paste', _listener, false);
    };

    function destroy() {
      global.removeEventListener('paste', _listener, false);
    }

    function _listener(pasteEvent) {
      _retrieveImageFromClipboardAsBlob(pasteEvent, function(imageBlob) {
        if(imageBlob){
          _clipboardPasteModal().promise().done(function() {
            var canvas = document.getElementById('clipboardPreview');
            var ctx = canvas.getContext('2d');
            var img = new Image();
            img.onload = function() {
                canvas.width = this.width;
                canvas.height = this.height;
                ctx.drawImage(img, 0, 0);
            };
            var URLObj = window.URL || window.webkitURL;
            img.src = URLObj.createObjectURL(imageBlob);
            var extension = imageBlob.name.slice(
              (Math.max(0, imageBlob.name.lastIndexOf(".")) || Infinity) + 1
            );
            $('#image-name').html('.' + extension); // add extension near file name
            // temporary store image blob
            UPLOADED_IMAGE = imageBlob
          });
        }
      });
    }

    function _retrieveImageFromClipboardAsBlob(pasteEvent, callback){
    	if(pasteEvent.clipboardData == false) {
          if(typeof(callback) == "function"){
            callback(undefined);
          }
        };

        var items = pasteEvent.clipboardData.items;
        if(items == undefined){
          if(typeof(callback) == "function"){
            callback(undefined);
          }
        };

        for (var i = 0; i < items.length; i++) {
          if (items[i].type.indexOf("image") == -1) continue;
          var blob = items[i].getAsFile();

          if(typeof(callback) == "function") {
            callback(blob);
          }
        }
    };

    // removes modal from dom
    function _destroyModalCallback() {
      var modal = $('#clipboardPreviewModal');
      modal.on('hidden.bs.modal', function() {
        modal.modal('hide').promise().done(function() {
          modal.remove();
        });
        UPLOADED_IMAGE = {};
      });
    }

    function _closeModal() {
      _hideModalForGood();
      $("#clipboardPreviewModal").remove();
    }

    // $(..).modal('hide') don't work properly so here we manually remove the
    // displayed modal
    function _hideModalForGood(){
      $("#clipboardPreviewModal").removeClass("in");
      $(".modal-backdrop").remove();
      $('body').removeClass('modal-open');
      $('body').css('padding-right', '');
      $("#clipboardPreviewModal").hide();
    }

    function _addImageCallback() {
      $('[data-action="addImageFormClipboard"]').on('click', function() {
        var inputArray = [];
        var newName = $('#clipboardImageName').val();
        // check if the name is set
        if( newName && newName.length > 0 ) {
          var extension = UPLOADED_IMAGE.name.slice(
            (Math.max(0, UPLOADED_IMAGE.name.lastIndexOf(".")) || Infinity) + 1
          );
          // hack to inject custom name in File object
          var name = newName + '.' + extension;
          var blob = UPLOADED_IMAGE.slice(0, UPLOADED_IMAGE.size, UPLOADED_IMAGE.type);
          // make new blob with the correct name;
          var newFile = new File([blob], name, { type: UPLOADED_IMAGE.type });
          inputArray.push(newFile);
        } else { // return the default name
          inputArray.push(UPLOADED_IMAGE);
        }

        // close modal
        _closeModal();
        // reuse file upload from drag'n drop :)
        if(LOCATION === 'steps') {
          DragNDropSteps.init(inputArray);
        } else  {
          DragNDropResults.init(inputArray);
        }
        // clear all uploaded images
        UPLOADED_IMAGE = {};
      });
    }

    // Generate modal html and hook callbacks
    function _clipboardPasteModal() {
      var html = '<div id="clipboardPreviewModal" class="modal fade" ';
      html += 'tabindex="-1" role="dialog" aria-hidden="true">';
      html += '<div class="modal-dialog" role="document">';
      html += '<div class="modal-content"><div class="modal-header">';
      html += '<button type="button" class="close" data-dismiss="modal"';
      html += ' aria-label="Close"><span aria-hidden="true">&times;</span>';
      html +=  '</button><h4 class="modal-title"><%= I18n.t('assets.from_clipboard.modal_title') %></h4>';
      html += '</div><div class="modal-body"><p><strong><%= I18n.t('assets.from_clipboard.image_preview') %></strong></p>';
      html += '<canvas style="border:1px solid grey;max-width:400px;max-height:300px" id="clipboardPreview" />';
      html += '<p><strong><%= I18n.t('assets.from_clipboard.file_name') %></strong></p>';
      html += '<div class="input-group">';
      html += '<input id="clipboardImageName" type="text" class="form-control" ';
      html += 'placeholder="<%= I18n.t('assets.from_clipboard.file_name_placeholder') %>" aria-describedby="image-name">';
      html += '<span class="input-group-addon" id="image-name"></span></div>';
      html += '</div><div class="modal-footer">';
      html += '<button type="button" class="btn btn-default" data-dismiss="modal"><%= I18n.t('general.cancel') %></button>';
      html += '<button type="button" class="btn btn-success" data-action="addImageFormClipboard"><%= I18n.t('assets.from_clipboard.add_image') %></button>';
      html += '</div></div></div></div><!-- /.modal -->';
      return $(html).appendTo($('body')).promise().done(function() {
        // display modal
        $('#clipboardPreviewModal').modal('show');
        // add callback to remove modal from DOM
        _destroyModalCallback();
        // add callback on image submit
        _addImageCallback();
      });
    }

    return Object.freeze({
      init: init,
      destroy: destroy
    });
  })();

  // Module to handle file uploading in Steps
  global.DragNDropSteps = (function() {
    var droppedFiles = [];
    var filesValid = true;
    var totalSize = 0;
    var fileMaxSizeMb;
    var fileMaxSize;

    function init(files) {
      fileMaxSizeMb = $(document.body).data('file-max-size-mb');
      fileMaxSize = fileMaxSizeMb * 1024 * 1024;
      for(var i = 0; i < files.length; i++) {
        droppedFiles.push(files[i]);
      }
      listItems();
    }

    // return the status of files if they are ready to submit
    function filesStatus() {
      return filesValid;
    }

    function clearFiles() {
      droppedFiles = [];
    }

    // loops through a list of files and display each file in a separate panel
    function listItems() {
      totalSize = 0;
      _enableSubmitButton();
      $('.panel-step-attachment-new').remove();
      _dragNdropAssetsOff();
      for(var i = 0; i < droppedFiles.length; i++) {
        $('#new-step-assets-group')
          .append(_uploadedAssetPreview(droppedFiles[i], i))
          .promise()
          .done(function() {
            _removeItemHandler(i);
          });
      }
      _validateTotalSize();
      dragNdropAssetsInit('steps');
    }

    // append the files to the form before submit
    function appendFilesToForm(ev) {
      var regex = /step\[assets_attributes\]\[[0-9]*\]\[id\]/;
      var prevEls = $('input').filter(function() {
        return this.name.match(regex);
      });
      var fd = new FormData($(ev.target).closest('form').get(0));
      for(var i = 0; i < droppedFiles.length; i++) {
        var index = i + prevEls.length;
        var name = 'step[assets_attributes][' + index + '][file]';
        fd.append(name, droppedFiles[i]);
      }

      filesValid = true;
      totalSize = 0;
      _dragNdropAssetsOff();
      return fd;
    }

    function _disableSubmitButton() {
      $('.step-save').prop('disabled', true);
    }

    function _enableSubmitButton() {
      $('.step-save').prop('disabled', false);
    }

    function _filerAndCheckFiles() {
      for(var i = 0; i < droppedFiles.length; i++) {
        if(droppedFiles[i].isValid == false) {
          return false;
        }
      }
      return (droppedFiles.length > 0);
    }

    function _validateFilesSize(file) {
      var fileSize = file.size;
      totalSize += parseInt(fileSize);
      if(fileSize > fileMaxSize) {
        file.isValid = false;
        _disableSubmitButton();
        return "<p class='dnd-error'>" + I18n.t('general.file.size_exceeded', { file_size: fileMaxSizeMb }) + '</p>';
      }
      return '';
    }

    function _validateTotalSize() {
      if(totalSize > fileMaxSize) {
        filesValid = false;
        _disableSubmitButton();
        $.each($('.panel-step-attachment-new'), function() {
          if(!$(this).find('p').hasClass('dnd-total-error')) {
            $(this)
              .find('.panel-body')
              .append("<p class='dnd-total-error'>" + I18n.t('general.file.total_size', { size: fileMaxSizeMb }) + '</p>');
          }
        });
      } else {
        $('.dnd-total-error').remove();
        if(_filerAndCheckFiles()) {
          filesValid = true;
          _enableSubmitButton();
        }
      }
    }

    function _uploadedAssetPreview(asset, i) {
      var html = '<div class="panel panel-default panel-step-attachment-new">';
      html += '<div class="panel-heading">';
      html += '<span class="fas fa-paperclip"></span>';
      html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>';
      html += '<div class="pull-right">';
      html += '<a data-item-id="' + i + '" href="#">';
      html += '<span class="fas fa-times"></span></a></div></div>';
      html += '<div class="panel-body">';
      html += '<label class="control-label">';
      html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>:</label> ';
      html += truncateLongString(asset.name,
                                 <%= Constants::FILENAME_TRUNCATION_LENGTH %>);
      html += _validateFilesSize(asset);
      html += '</div></div>';
      return html;
    }

    function _removeItemHandler(id) {
      $('[data-item-id="' + id +'"]').off('click').on('click', function(e) {
        e.preventDefault();
        e.stopImmediatePropagation();
        e.stopPropagation();
        var $el = $(this);
        var index = $el.data('item-id');
        totalSize -= parseInt(droppedFiles[index].size);
        droppedFiles.splice(index, 1);
        listItems();
      });
    }

    function _dragNdropAssetsOff() {
      $('body').off('drag dragstart dragend dragover dragenter dragleave drop');
      $('.is-dragover').hide();
      // remove listeners for clipboard images
      copyFromClipboard.destroy();
    }

    return Object.freeze({
      init: init,
      appendFilesToForm: appendFilesToForm,
      listItems: listItems,
      filesStatus: filesStatus,
      clearFiles: clearFiles
    });
  })();

  // Module to handle file uploading in Results
  global.DragNDropResults = (function() {
    var droppedFiles = [];
    var isValid = true;
    var totalSize = 0;
    var fileMaxSizeMb;
    var fileMaxSize;

    function init(files) {
      fileMaxSizeMb = $(document.body).data('file-max-size-mb');
      fileMaxSize = fileMaxSizeMb * 1024 * 1024;
      for(var i = 0; i < files.length; i++) {
        droppedFiles.push(files[i]);
      }
      listItems();
    }

    // return the status of files if they are ready to submit
    function filesStatus() {
      return isValid;
    }

    // loops through a list of files and display each file in a separate panel
    function listItems() {
      totalSize = 0;
      $('.panel-result-attachment-new').remove();
      if(droppedFiles.length < 1) {
        _disableSubmitButton();
      } else {
        _dragNdropAssetsOff();
        for(var i = 0; i < droppedFiles.length; i++) {
            $('#new-result-assets-select')
              .after(_uploadedAssetPreview(droppedFiles[i], i))
              .promise()
              .done(function() {
                _removeItemHandler(i);
              });
        }
        _validateTotalSize();
        dragNdropAssetsInit('results');
      }
    }

    // appent the files to the form before submit
    function _appendFilesToForm() {
      var regex = /result\[assets_attributes\]\[[0-9]*\]\[id\]/;
      var prevEls = $('input').filter(function() {
        return this.name.match(regex);
      });

      var fd = new FormData();
      var result_names = [];
      $.each($('input[rel="results[name]"]'), function() {
        result_names.push($(this).val());
      });
      result_names.reverse();
      for(var i = 0; i < droppedFiles.length; i++) {
        var index = i + prevEls.length;
        var file_name = 'results_files[' + index + ']';
        fd.append(file_name, droppedFiles[i]);
        fd.append('results_names[' + i + ']', result_names[i]);
      }
      destroyAll();
      return fd;
    }

    function _disableSubmitButton() {
      $('.save-result').prop('disabled', true);
    }

    function _enableSubmitButton() {
      $('.save-result').prop('disabled', false);
    }

    function _filerAndCheckFiles() {
      for(var i = 0; i < droppedFiles.length; i++) {
        if(droppedFiles[i].isValid == false) {
          return false;
        }
      }
      return (droppedFiles.length > 0);
    }

    function _validateFilesSize(file) {
      var fileSize = file.size;
      totalSize += parseInt(fileSize);
      if(fileSize > fileMaxSize) {
        file.isValid = false;
        _disableSubmitButton();
        return "<p class='dnd-error'>" + I18n.t('general.file.size_exceeded', { file_size: fileMaxSizeMb }) + '</p>';
      }
      return '';
    }

    function _validateTotalSize() {
      if(totalSize > fileMaxSize) {
        isValid = false;
        _disableSubmitButton();
        $.each($('.panel-result-attachment-new'), function() {
          if(!$(this).find('p').hasClass('dnd-total-error')) {
            $(this)
              .find('.panel-body')
              .append("<p class='dnd-total-error'>" + I18n.t('general.file.total_size', { size: fileMaxSizeMb }) + '</p>');
            }
        });
      } else {
        $('.dnd-total-error').remove();
        if(_filerAndCheckFiles()) {
          isValid = true;
          _enableSubmitButton();
        }
      }
    }

    function validateTextSize(input) {
      if(input.value.length > <%= Constants::NAME_MAX_LENGTH %>) {
        $(input).parent().find('.dnd-error').remove();
        $(input).after("<p class='dnd-error'><%= I18n.t('general.text.length_too_long', max_length: Constants::NAME_MAX_LENGTH) %></p>");
        isValid = false;
      } else {
        $(input).parent().find('.dnd-error').remove();
        isValid = true;
      }
    }

    function _uploadedAssetPreview(asset, i) {
      var html = '<div class="panel panel-default panel-result-attachment-new">';
      html += '<div class="panel-heading">';
      html += '<span class="fas fa-paperclip"></span>';
      html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>';
      html += '<div class="pull-right">';
      html += '<a data-item-id="' + i + '" href="#">';
      html += '<span class="fas fa-times"></span></a></div></div>';
      html += '<div class="panel-body"><div class="form-group">';
      html += '<label class="control-label">Name</label>';
      html += '<input type="text" class="form-control" ';
      html += 'onChange="DragNDropResults.validateTextSize(this)"';
      html += ' rel="results[name]" name="results[name][' + i + ']">';
      html += '</div><div class="form-group"><label class="control-label">';
      html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>:</label> ';
      html += truncateLongString(asset.name,
                                 <%= Constants::FILENAME_TRUNCATION_LENGTH %>);
      html += _validateFilesSize(asset);
      html += '</div></div>';
      return html;
    }

    function _removeItemHandler(id) {
      $('[data-item-id="' + id +'"]').off('click').on('click', function(e) {
        e.preventDefault();
        e.stopImmediatePropagation();
        e.stopPropagation();
        var $el = $(this);
        var index = $el.data('item-id');
        totalSize -= parseInt(droppedFiles[index].size);
        droppedFiles.splice(index, 1);
        listItems();
      });
    }

    function processResult(button) {
      if(isValid && _filerAndCheckFiles()) {
        animateSpinner();
        $.ajax({
          url: $(button).attr('data-href'),
          method: 'POST',
          data: _appendFilesToForm(),
          contentType: false,
          processData: false,
          success: function(data) {
            animateSpinner(null, false);
            $('#new-result-assets-select').parent().remove();
            $(data.html).prependTo('#results').promise().done(function() {
              $.each($('[data-container="new-reports"]').find('.result'),
                     function() {
                initFormSubmitLinks($(this));
                ResutlAssets.applyEditResultAssetCallback();
                Results.applyCollapseLinkCallBack();
                Results.toggleResultEditButtons(true);
                initPreviewModal();
                Comments.initialize();
                ResutlAssets.initNewResultAsset();
                Results.expandResult($(this));
              });

            });
            $('#results-toolbar').show();
          },
          error: function() {
            animateSpinner();
            location.reload();
          }
        })
      }
    }

    function destroyAll() {
      _dragNdropAssetsOff();
      droppedFiles = [];
      isValid = true;
      totalSize = 0;
    }

    function _dragNdropAssetsOff() {
      $('body').off('drag dragstart dragend dragover dragenter dragleave drop');
      $('.is-dragover').hide();
    }

    return Object.freeze({
      init: init,
      listItems: listItems,
      destroyAll: destroyAll,
      filesStatus: filesStatus,
      validateTextSize: validateTextSize,
      processResult: processResult
    });
  })();

  global.dragNdropAssetsInit = function(location) {
    var in_window = true;

    $('body').on('drag dragstart dragend dragover dragenter dragleave drop',
             function(e) {
      e.preventDefault();
      e.stopPropagation();
    }).on('dragover', function() {
      in_window = true;
      $('.is-dragover').show();
    }).on('dragleave', function() {
      in_window = false;
      setTimeout(function() {
        if(!in_window) {
          $('.is-dragover').hide();
        }
      }, 5000);

    }).on('drop', function(e) {
      $('.is-dragover').hide();
      var files = e.originalEvent.dataTransfer.files;
      if(location === 'steps') {
        DragNDropSteps.init(files);
      } else  {
        DragNDropResults.init(files);
      }
    });

    copyFromClipboard.init(location);
  }

})(window);
