/*
     $Revision$
     $Id$

     File:          attachments.js
     Description:   clientside functions for attachments
     Note:          Wordt nog alleen voor PDA gebruikt
                    Een bestand wordt na kiezen altijd direct geupload en
                    dan krijgen we een token terug welke we uiteindelijk
                    submitten

                    Er zit ook drag-and-drop code in die we (nog) niet gebruiken
*/

async function resizeFile(file, inputEl)
{
  var maxWidth = inputEl.getAttribute("data-max-default-width");
  var maxHeight = inputEl.getAttribute("data-max-default-height");
  // Verkleinen voor alle browsers behalve Internet Explorer.
  var clientresize = (typeof createImageBitmap == "function" ? "1" : "0");

  if (clientresize && maxWidth > 0 && maxHeight > 0)
  {
    var canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = await createImageBitmap(file);
    if (img.width > maxWidth && img.height > maxHeight) // drempel voor verkleining van de afbeelding.
    {
      var ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
      var width = img.width * ratio + .5 | 0;
      var height = img.height * ratio + .5 | 0;
      // resize the canvas to the new dimensions
      canvas.width = width;
      canvas.height = height;
      // scale & draw the image onto the canvas
      ctx.drawImage(img, 0, 0, width, height);
      // Get the binary (blob)
      var blob = await new Promise(rs => canvas.toBlob(rs, "image/jpeg", 1));
      var resizedFile = new File([blob], file.name, file);
      return resizedFile;
    }
    else
      return file;
  }
  else
    return file;
}

function addFile(inputEl, file, eagerUpload) {
  var attachmentsFields = $(inputEl).closest('.attachments_form').find('.attachments_fields');
  var multi = $(inputEl).attr('multiple') == 'multiple'; // kenmerktype == [M]ap
  var maxFiles = (multi ? 10 : 1);

  if (attachmentsFields.children().length < maxFiles) {
    var attachmentId = addFile.nextAttachmentId++;
    var fileSpan = $('<span>', { id: 'attachments_' + attachmentId });
    var param = $(inputEl).data('param');
    if (!param) {param = 'attachments'};
    var kval = $(inputEl).siblings("a[role=button]").attr("id"); // De 'Toevoegen' knop heeft de kval (bijv 'k123val') als id
    if (!multi) { // kenmerktype != [M]ap
      fileSpan.append(
          $('<input>', { type: 'hidden', name: kval } ).val(file.name) // Dit veld is nodig voor kenmerktypes [E] & [F] om de bestandsnaam als kenmerkwaarde op te slaan
      );
    }
    fileSpan.append(
        $('<input>', { type: 'text',
                       class : 'icon icon-attachment filename readonly form-control-plaintext',
                       id: param + "_" + attachmentId + "_file",
                       name: param + '[' + attachmentId + '][filename]',
                       readonly: 'readonly'
                     } ).val(file.name),
        $('<input>', { type: 'hidden', 'class': 'token', name: param + '[' + attachmentId + '][token]'} )
        /* Gelijk een Delete knop invoegen is wat te complex */
    ).appendTo(attachmentsFields);

    if(eagerUpload) {
      ajaxUpload(file, attachmentId, fileSpan, inputEl);
    }

    return attachmentId;
  }
  return null;
}

addFile.nextAttachmentId = 1;

function ajaxUpload(file, attachmentId, fileSpan, inputEl) {

  function onLoadstart(e) {
    fileSpan.removeClass('ajax-waiting');
    fileSpan.addClass('ajax-loading');
    $('input:submit', $(this).parents('form')).attr('disabled', 'disabled');
  }

  function onProgress(e) {
    if(e.lengthComputable) {
     this.progressbar( 'value', e.loaded * 100 / e.total );
    }
  }

  async function actualUpload(file, attachmentId, fileSpan, inputEl)
  {
    ajaxUpload.uploading++;
    // Bestanden verkleinen volgens de standaard formattering.
    var resizedFile = await resizeFile(file, inputEl);

    uploadBlob(resizedFile, $(inputEl).data('upload-path'), attachmentId, {
        loadstartEventHandler: onLoadstart.bind(progressSpan),
        progressEventHandler: onProgress.bind(progressSpan)
      })
      .done(function(result) {
        if ("success" in result && !result.success)
        {
          FcltMgr.alert(result.message);
          return;
        }
        addInlineAttachmentMarkup(resizedFile);
        progressSpan.progressbar( 'value', 100 ).remove();
        fileSpan.find('input.token').val(result.attachment.token);

        // Bestandsnaam kan aangepast zijn. Bestandsnaam opnieuw zetten.
        var param = $(inputEl).data('param');
        var filename = param + "_" + attachmentId + "_file";
        $("#" + filename).val(result.attachment.name);
      })
      .fail(function(result) {
        progressSpan.text(result.statusText);
      }).always(function() {
        ajaxUpload.uploading--;
        fileSpan.removeClass('ajax-loading');
        var form = fileSpan.parents('form');
        if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) {
          $('input:submit', form).removeAttr('disabled');
        }
        form.dequeue('upload');
      });
  }

  var progressSpan = $('<div>').insertAfter(fileSpan.find('input.filename'));
  progressSpan.progressbar({
    classes: {
      "ui-progressbar": "highlight"
    }
  });
  fileSpan.addClass('ajax-waiting');

  var maxSyncUpload = 1; // || $(inputEl).data('max-concurrent-uploads');

  if(maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload)
    actualUpload(file, attachmentId, fileSpan, inputEl);
  else
    $(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, attachmentId, fileSpan, inputEl));
}

ajaxUpload.uploading = 0;

function removeFile() {
  $(this).closest('.attachments_form').find('.add_attachment').show();
  $(this).parent('span').remove();
  return false;
}

function uploadBlob(blob, uploadUrl, attachmentId, options) {

  var actualOptions = $.extend({
    loadstartEventHandler: $.noop,
    progressEventHandler: $.noop
  }, options);

  uploadUrl = uploadUrl + encodeURIComponent(blob.name) + '?attachment_id=' + attachmentId;
  if (blob instanceof window.File) {
    uploadUrl += '&content_type=' + encodeURIComponent(blob.type);
  }

  return $.ajax(uploadUrl, {
    type: 'POST',
    contentType: 'application/octet-stream',
    beforeSend: function(jqXhr, settings) {
      jqXhr.setRequestHeader('Accept', 'application/json');

      jqXhr.setRequestHeader('X-CSRF-TOKEN', RVT_token );

      // attach proper File object
      settings.data = blob;
    },
    xhr: function() {
      var xhr = $.ajaxSettings.xhr();
      xhr.upload.onloadstart = actualOptions.loadstartEventHandler;
      xhr.upload.onprogress = actualOptions.progressEventHandler;
      return xhr;
    },
    data: blob,
    cache: false,
    processData: false
  });
}

function addInputFiles(inputEl) {
  //var attachmentsFields = $(inputEl).closest('.attachments_form').find('.attachments_fields');
  var attachementDiv = $(inputEl).closest('.attachments_form');
  var addAttachment = $(inputEl).closest('.attachments_form').find('.add_attachment');
  var clearedFileInput = $(inputEl).clone().val('');
  var sizeExceeded = false;
  var param = $(inputEl).data('param');
  if (!param) {param = 'attachments'};

  if ($.ajaxSettings.xhr().upload && inputEl.files) {
    // upload files using ajax
    sizeExceeded = uploadAndAttachFiles(inputEl.files, inputEl);
    $(inputEl).remove();
  } else { // Volgens mij is deze tak niet meer nodig sinds IE10
    // browser not supporting the file API, upload on form submission
    var attachmentId;
    var aFilename = inputEl.value.split(/\/|\\/);
    attachmentId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false);
    if (attachmentId) {
      $(inputEl).attr({ name: param + '[' + attachmentId + '][file]', style: 'display:none;' }).appendTo('#attachments_' + attachmentId);
    }
  }

  clearedFileInput.prependTo(addAttachment);
  attachementDiv.trigger("create");
  let $bijlageButton = addAttachment.find("[data-role=button][nBijlagen]");
  if ($bijlageButton.length) {
    $bijlageButton.attr("nBijlagen", parseInt($bijlageButton.attr("nBijlagen") || 0, 10) + inputEl.files.length);
  }
}

function uploadAndAttachFiles(files, inputEl)
{
  var maxFileSize = $(inputEl).data('max-file-size');
  var maxFileSizeExceeded = $(inputEl).data('max-file-size-message');

  var sizeExceeded = false;
  $.each(files, function() {
    if (this.size && maxFileSize != null && this.size > parseInt(maxFileSize)) {sizeExceeded=true;}
  });
  if (sizeExceeded) {
    FcltMgr.alert(maxFileSizeExceeded);
  } else {
    $.each(files, function() {addFile(inputEl, this, true);});
  }
  return sizeExceeded;
}

function handleFileDropEvent(e) {

  $(this).removeClass('fileover');
  blockEventPropagation(e);

  if ($.inArray('Files', e.dataTransfer.types) > -1) {
    handleFileDropEvent.target = e.target;
    uploadAndAttachFiles(e.dataTransfer.files, $('input:file.filedrop').first());
  }
}
handleFileDropEvent.target = '';

function dragOverHandler(e) {
  $(this).addClass('fileover');
  blockEventPropagation(e);
}

function dragOutHandler(e) {
  $(this).removeClass('fileover');
  blockEventPropagation(e);
}

function setupFileDrop() {
  if (window.File && window.FileList && window.ProgressEvent && window.FormData) {

    // $.event.fixHooks.drop = { props: [ 'dataTransfer' ] };

    $('form div.box:not(.filedroplistner)').has('input:file.filedrop').each(function() {
      $(this).on({
          dragover: dragOverHandler,
          dragleave: dragOutHandler,
          drop: handleFileDropEvent
      }).addClass('filedroplistner');
    });
  }
}

function addInlineAttachmentMarkup(file) {
  // insert uploaded image inline if dropped area is currently focused textarea
  if($(handleFileDropEvent.target).hasClass('wiki-edit') && $.inArray(file.type, window.wikiImageMimeTypes) > -1) {
    var $textarea = $(handleFileDropEvent.target);
    var cursorPosition = $textarea.prop('selectionStart');
    var description = $textarea.val();
    var sanitizedFilename = file.name.replace(/[\/\?\%\*\:\|\"\'<>\n\r]+/, '_');
    var inlineFilename = encodeURIComponent(sanitizedFilename);
    var newLineBefore = true;
    var newLineAfter = true;
    if(cursorPosition === 0 || description.substr(cursorPosition-1,1).match(/\r|\n/)) {
      newLineBefore = false;
    }
    if(description.substr(cursorPosition,1).match(/\r|\n/)) {
      newLineAfter = false;
    }

    $textarea.val(
      description.substring(0, cursorPosition)
      + (newLineBefore ? '\n' : '')
      + inlineFilename
      + (newLineAfter ? '\n' : '')
      + description.substring(cursorPosition, description.length)
    );

    $textarea.prop({
      'selectionStart': cursorPosition + newLineBefore,
      'selectionEnd': cursorPosition + inlineFilename.length + newLineBefore
    });
    $textarea.closest('.jstEditor')
      .siblings('.jstElements')
      .find('.jstb_img').click();

    // move cursor into next line
    cursorPosition = $textarea.prop('selectionStart');
    $textarea.prop({
      'selectionStart': cursorPosition + 1,
      'selectionEnd': cursorPosition + 1
    });

  }
}

$(setupFileDrop);

$(function()
{
  $("input.deleted_attachment").change(function(){
    $(this).parents('.existing-attachment').toggleClass('deleted', $(this).is(":checked"));
  }).change();
});
