(function() {
  'use strict';

  window.utils = window.utils || {};

  var ASYNC_TABLE_CONTENT_CHANGED_CLASS = 'async-table--changed';
  var JS_INITIALIZED_CLASS = 'js-check-all-initialized';
  var CHECKBOX_SELECTOR    = '[type="checkbox"]';

  function getCheckboxId() {
    return 'check-all-checkbox-' + Math.floor(Math.random() * 100000);
  }

  window.utils.checkAll = function(wrapper, options) {

    if ((!wrapper || wrapper.classList.contains(JS_INITIALIZED_CLASS)) && !wrapper.classList.contains(ASYNC_TABLE_CONTENT_CHANGED_CLASS)) {
      return false;
    }
    options = options || {};

    var columns = [];
    var checkboxColumn = [];
    var checkAllCheckbox = null;

    var utilInstances = [];

    function init() {

      columns = gatherColumns(wrapper);

      setupCheckAllCheckbox(findCheckboxColumn(columns));

      wrapper.classList.add(JS_INITIALIZED_CLASS);
    }

    function gatherColumns(table) {
      var rows = Array.from(table.querySelectorAll('tr'));
      var cols = [];
      rows.forEach(function(tr) {
        var cells = Array.from(tr.querySelectorAll('td'));
        cells.forEach(function(cell, cellIndex) {
          if (!cols[cellIndex]) {
            cols[cellIndex] = [];
          }
          cols[cellIndex].push(cell);
        });
      });
      return cols;
    }

    function findCheckboxColumn(columns) {
      var checkboxColumnId = null;
      columns.forEach(function(col, i) {
        if (isCheckboxColumn(col)) {
          checkboxColumnId = i;
        }
      });
      return checkboxColumnId;
    }

    function isCheckboxColumn(col) {
      var onlyCheckboxes = true;
      col.forEach(function(cell) {
        if (onlyCheckboxes && !cell.querySelector(CHECKBOX_SELECTOR)) {
          onlyCheckboxes = false;
        }
      });
      return onlyCheckboxes;
    }

    function setupCheckAllCheckbox(columnId) {
      if (columnId === null) {
        return;
      }

      checkboxColumn = columns[columnId];
      var firstRow = wrapper.querySelector('tr');
      var th = Array.from(firstRow.querySelectorAll('th, td'))[columnId];
      th.innerHTML = 'test';
      checkAllCheckbox = document.createElement('input');
      checkAllCheckbox.setAttribute('type', 'checkbox');
      checkAllCheckbox.setAttribute('id', getCheckboxId());
      th.innerHTML = '';
      th.insertBefore(checkAllCheckbox, null);
      utilInstances.push(window.utils.setup('checkbox', checkAllCheckbox));

      checkAllCheckbox.addEventListener('input', onCheckAllCheckboxInput);
      setupCheckboxListeners();
    }

    function onCheckAllCheckboxInput() {
      toggleAll(checkAllCheckbox.checked);
    }

    function setupCheckboxListeners() {
      checkboxColumn
        .map(function(cell) {
          return cell.querySelector(CHECKBOX_SELECTOR);
        })
        .forEach(function(checkbox) {
          checkbox.addEventListener('input', updateCheckAllCheckboxState);
        });
    }

    function updateCheckAllCheckboxState() {
      var allChecked = checkboxColumn.reduce(function(acc, cell) {
        return acc && cell.querySelector(CHECKBOX_SELECTOR).checked;
      }, true);
      checkAllCheckbox.checked = allChecked;
    }

    function toggleAll(checked) {
      checkboxColumn.forEach(function(cell) {
        cell.querySelector(CHECKBOX_SELECTOR).checked = checked;
      });
    }

    function destroy() {
      utilInstances.forEach(function(util) {
        util.destroy();
      });
    }

    init();

    return {
      scope: wrapper,
      destroy: destroy,
    };
  };
})();
