(function() {
  'use strict';

  var inputUtilities = [];

  /**
   *
   * FileInput Utility
   *  wraps native file input
   *
   * Attribute: uw-file-input
   *  (element must be an input of type='file')
   *
   * Example usage:
   * <input type='file' uw-file-input>
   *
   * Internationalization:
   *  This utility expects the following translations to be available:
   *    »filesSelected«: label of multi-input button after selection
   *      example: "Dateien ausgewählt" (will be prepended by number of selected files)
   *    »selectFile«: label of single-input button before selection
   *      example: "Datei auswählen"
   *    »selectFiles«: label of multi-input button before selection
   *      example: "Datei(en) auswählen"
   *
   */

  var FILE_INPUT_UTIL_NAME = 'fileInput';
  var FILE_INPUT_UTIL_SELECTOR = 'input[type="file"][uw-file-input]';

  var FILE_INPUT_CLASS = 'file-input';
  var FILE_INPUT_INITIALIZED_CLASS = 'file-input--initialized';
  var FILE_INPUT_LIST_CLASS = 'file-input__list';
  var FILE_INPUT_UNPACK_CHECKBOX_CLASS = 'file-input__unpack';
  var FILE_INPUT_LABEL_CLASS = 'file-input__label';

  var fileInputUtil = function(element) {
    var isMultiFileInput = false;
    var fileList;
    var label;

    function init() {
      if (!element) {
        throw new Error('FileInput utility cannot be setup without an element!');
      }

      if (element.classList.contains(FILE_INPUT_INITIALIZED_CLASS)) {
        throw new Error('FileInput utility already initialized!');
      }

      // check if is multi-file input
      isMultiFileInput = element.hasAttribute('multiple');
      if (isMultiFileInput) {
        fileList = createFileList();
      }

      label = createFileLabel();
      updateLabel();

      // add change listener
      element.addEventListener('change', function() {
        updateLabel();
        renderFileList();
      });

      // add util class for styling and mark as initialized
      element.classList.add(FILE_INPUT_CLASS, FILE_INPUT_INITIALIZED_CLASS);

      return {
        name: FILE_INPUT_UTIL_NAME,
        element: element,
        destroy: function() {},
      };
    }

    function renderFileList() {
      if (!fileList) {
        return;
      }

      var files = element.files;
      fileList.innerHTML = '';
      Array.from(files).forEach(function(file) {
        var fileDisplayEl = document.createElement('li');
        fileDisplayEl.innerHTML = file.name;
        fileList.appendChild(fileDisplayEl);
      });
    }

    function createFileList() {
      var list = document.createElement('ol');
      list.classList.add(FILE_INPUT_LIST_CLASS);
      var unpackEl = element.parentElement.querySelector('.' + FILE_INPUT_UNPACK_CHECKBOX_CLASS);
      if (unpackEl) {
        element.parentElement.insertBefore(list, unpackEl);
      } else {
        element.parentElement.appendChild(list);
      }
      return list;
    }

    function createFileLabel() {
      var label = document.createElement('label');
      label.classList.add(FILE_INPUT_LABEL_CLASS);
      label.setAttribute('for', element.id);
      element.parentElement.insertBefore(label, element);
      return label;
    }

    function updateLabel() {
      var files = element.files;
      if (files && files.length) {
        label.innerText = isMultiFileInput ? files.length + ' ' + I18n.get('filesSelected') : files[0].name;
      } else {
        label.innerText = isMultiFileInput ? I18n.get('selectFiles') : I18n.get('selectFile');
      }
    }

    return init();
  }

  inputUtilities.push({
    name: FILE_INPUT_UTIL_NAME,
    selector: FILE_INPUT_UTIL_SELECTOR,
    setup: fileInputUtil,
  })

  /**
   *
   * Checkbox Utility
   *  wraps native checkbox
   *
   * Attribute: (none)
   *  (element must be an input of type="checkbox")
   *
   * Example usage:
   * <input type="checkbox">
   *
   */

  var CHECKBOX_UTIL_NAME = 'checkbox';
  var CHECKBOX_UTIL_SELECTOR = 'input[type="checkbox"]';

  var CHECKBOX_CLASS = 'checkbox';
  var CHECKBOX_INITIALIZED_CLASS = 'checkbox--initialized';

  var checkboxUtil = function(element) {

    function init() {
      if (!element) {
        throw new Error('Checkbox utility cannot be setup without an element!');
      }

      if (element.classList.contains(CHECKBOX_INITIALIZED_CLASS)) {
        // throw new Error('Checkbox utility already initialized!');
        return false;
      }

      if (element.parentElement.classList.contains(CHECKBOX_CLASS)) {
        // throw new Error('Checkbox element\'s wrapper already has class "' + CHECKBOX_CLASS + '"!');
        return false;
      }

      var siblingEl = element.nextSibling;
      var parentEl = element.parentElement;

      var wrapperEl = document.createElement('div');
      wrapperEl.classList.add(CHECKBOX_CLASS);

      var labelEl = document.createElement('label');
      labelEl.setAttribute('for', element.id);

      wrapperEl.appendChild(element);
      wrapperEl.appendChild(labelEl);

      parentEl.insertBefore(wrapperEl, siblingEl);

      element.classList.add(CHECKBOX_INITIALIZED_CLASS);

      return {
        name: CHECKBOX_UTIL_NAME,
        element: element,
        destroy: function() {},
      };
    }

    return init();
  }

  inputUtilities.push({
    name: CHECKBOX_UTIL_NAME,
    selector: CHECKBOX_UTIL_SELECTOR,
    setup: checkboxUtil,
  });

  // register the collected input utilities
  if (UtilRegistry) {
    inputUtilities.forEach(UtilRegistry.register);
  }
})();
