(function () {
  'use strict';

  var ENHANCED_ATTR = 'data-checkbox-multiselect-enhanced';

  function optionList(select) {
    return Array.prototype.slice.call(select.options).filter(function (option) {
      return option.value !== '';
    });
  }

  function selectedOptions(select) {
    return optionList(select).filter(function (option) {
      return option.selected;
    });
  }

  function selectedLabel(select) {
    var selectedCount = selectedOptions(select).length;
    if (selectedCount === 0) {
      return select.dataset.emptyLabel || 'Nic nie wybrano';
    }

    var suffix = selectedCount === 1
      ? (select.dataset.selectedLabelSingular || 'zaznaczono')
      : (select.dataset.selectedLabelPlural || 'zaznaczono');

    return selectedCount + ' ' + suffix;
  }

  function setOpen(wrapper, isOpen) {
    wrapper.classList.toggle('is-open', isOpen);
    wrapper.querySelector('.checkbox-multiselect__trigger').setAttribute('aria-expanded', isOpen ? 'true' : 'false');
  }

  function updateAllState(select, allCheckbox) {
    var options = optionList(select);
    var selectedCount = selectedOptions(select).length;

    allCheckbox.checked = options.length > 0 && selectedCount === options.length;
    allCheckbox.indeterminate = selectedCount > 0 && selectedCount < options.length;
  }

  function syncTrigger(select, wrapper) {
    wrapper.querySelector('.checkbox-multiselect__value').textContent = selectedLabel(select);
    updateAllState(select, wrapper.querySelector('.checkbox-multiselect__all'));
  }

  function createCheckbox(option, select, wrapper, index) {
    var row = document.createElement('label');
    row.className = 'checkbox-multiselect__option';

    var checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.checked = option.selected;
    checkbox.value = option.value;
    checkbox.dataset.optionIndex = String(index);

    var text = document.createElement('span');
    text.textContent = option.text;

    checkbox.addEventListener('change', function () {
      option.selected = checkbox.checked;
      syncTrigger(select, wrapper);
      select.dispatchEvent(new Event('change', { bubbles: true }));
    });

    row.appendChild(checkbox);
    row.appendChild(text);

    return row;
  }

  function enhanceSelect(select) {
    if (select.hasAttribute(ENHANCED_ATTR)) {
      return;
    }

    var wrapper = document.createElement('div');
    wrapper.className = 'checkbox-multiselect';

    var trigger = document.createElement('button');
    trigger.type = 'button';
    trigger.className = 'checkbox-multiselect__trigger';
    trigger.setAttribute('aria-haspopup', 'listbox');
    trigger.setAttribute('aria-expanded', 'false');

    var value = document.createElement('span');
    value.className = 'checkbox-multiselect__value';
    value.textContent = selectedLabel(select);

    var arrow = document.createElement('span');
    arrow.className = 'checkbox-multiselect__arrow';
    arrow.setAttribute('aria-hidden', 'true');

    var dropdown = document.createElement('div');
    dropdown.className = 'checkbox-multiselect__dropdown';
    dropdown.setAttribute('role', 'listbox');

    var allRow = document.createElement('label');
    allRow.className = 'checkbox-multiselect__option checkbox-multiselect__option--all';

    var allCheckbox = document.createElement('input');
    allCheckbox.type = 'checkbox';
    allCheckbox.className = 'checkbox-multiselect__all';

    var allText = document.createElement('span');
    allText.textContent = select.dataset.allLabel || 'Wszystkie';

    allCheckbox.addEventListener('change', function () {
      var shouldSelect = allCheckbox.checked;
      optionList(select).forEach(function (option) {
        option.selected = shouldSelect;
      });
      wrapper.querySelectorAll('.checkbox-multiselect__option input:not(.checkbox-multiselect__all)').forEach(function (checkbox) {
        checkbox.checked = shouldSelect;
      });
      syncTrigger(select, wrapper);
      select.dispatchEvent(new Event('change', { bubbles: true }));
    });

    allRow.appendChild(allCheckbox);
    allRow.appendChild(allText);
    dropdown.appendChild(allRow);

    optionList(select).forEach(function (option, index) {
      dropdown.appendChild(createCheckbox(option, select, wrapper, index));
    });

    trigger.appendChild(value);
    trigger.appendChild(arrow);
    wrapper.appendChild(trigger);
    wrapper.appendChild(dropdown);

    select.parentNode.insertBefore(wrapper, select);
    wrapper.appendChild(select);
    select.setAttribute(ENHANCED_ATTR, '1');

    trigger.addEventListener('click', function () {
      setOpen(wrapper, !wrapper.classList.contains('is-open'));
    });

    wrapper.addEventListener('keydown', function (event) {
      if (event.key === 'Escape') {
        setOpen(wrapper, false);
        trigger.focus();
      }
    });

    syncTrigger(select, wrapper);
  }

  document.addEventListener('click', function (event) {
    document.querySelectorAll('.checkbox-multiselect.is-open').forEach(function (wrapper) {
      if (!wrapper.contains(event.target)) {
        setOpen(wrapper, false);
      }
    });
  });

  document.addEventListener('DOMContentLoaded', function () {
    document.querySelectorAll('select[data-checkbox-multiselect]').forEach(enhanceSelect);
  });
}());
