(function() {

  var MASS_INPUT_SELECTOR = '.massinput';
  var RECIPIENT_CATEGORIES_SELECTOR = '.recipient-categories';
  var RECIPIENT_CATEGORY_SELECTOR = '.recipient-category';
  var RECIPIENT_CATEGORY_CHECKBOX_SELECTOR = '.recipient-category__checkbox ';
  var RECIPIENT_CATEGORY_OPTIONS_SELECTOR = '.recipient-category__options';
  var RECIPIENT_CATEGORY_TOGGLE_ALL_SELECTOR = '.recipient-category__toggle-all [type="checkbox"]';
  var RECIPIENT_CATEGORY_CHECKED_COUNTER_SELECTOR = '.recipient-category__checked-counter';

  var massInputElement;

  document.addEventListener('DOMContentLoaded', function() {
    var recipientCategoriesElement = document.querySelector(RECIPIENT_CATEGORIES_SELECTOR);
    massInputElement = recipientCategoriesElement.closest(MASS_INPUT_SELECTOR);

    setupRecipientCategories();

    var recipientObserver = new MutationObserver(setupRecipientCategories);
    recipientObserver.observe(massInputElement, { childList: true });
  });

  function setupRecipientCategories() {
    var recipientCategoryElements = Array.from(massInputElement.querySelectorAll(RECIPIENT_CATEGORY_SELECTOR));

    recipientCategoryElements.forEach(function(element) {
      setupRecipientCategory(element);
    });
  }

  function setupRecipientCategory(recipientCategoryElement) {
    var categoryCheckbox = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_CHECKBOX_SELECTOR);
    var categoryOptions = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_OPTIONS_SELECTOR);
    if (categoryOptions) {

      var categoryCheckboxes = Array.from(categoryOptions.querySelectorAll('[type="checkbox"]'));
      var toggleAllCheckbox = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_TOGGLE_ALL_SELECTOR);

      // setup category checkbox to toggle all child checkboxes if changed
      categoryCheckbox.addEventListener('change', function() {
        categoryCheckboxes.forEach(function(checkbox) {
          checkbox.checked = categoryCheckbox.checked;
        });
        updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
        updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes);
      });

      // update counter and toggle checkbox initially
      updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
      updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes);

      // register change listener for individual checkboxes
      categoryCheckboxes.forEach(function(checkbox) {
        checkbox.addEventListener('change', function() {
          updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
          updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes);
        });
      });

      // register change listener for toggle all checkbox
      if (toggleAllCheckbox) {
        toggleAllCheckbox.addEventListener('change', function() {
          categoryCheckboxes.forEach(function(checkbox) {
            checkbox.checked = toggleAllCheckbox.checked;
          });
          updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
        });
      }
    }
  }

  // update checked state of toggle all checkbox based on all other checkboxes
  function updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes) {
    var allChecked = categoryCheckboxes.reduce(function(acc, checkbox) {
      return acc && checkbox.checked;
    }, true);
    toggleAllCheckbox.checked = allChecked;
  }

  // update value of checked counter
  function updateCheckedCounter(recipientCategoryElement, categoryCheckboxes) {
    var checkedCounter = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_CHECKED_COUNTER_SELECTOR);
    var checkedCheckboxes = categoryCheckboxes.reduce(function(acc, checkbox) { return checkbox.checked ? acc + 1 : acc; }, 0);
    checkedCounter.innerHTML = checkedCheckboxes + '/' + categoryCheckboxes.length;
  }

})();
