(function() {
  'use strict';

  /**
   *
   * Check All Checkbox Utility
   *  adds a Check All Checkbox above columns with only checkboxes
   *
   * Attribute: [none]
   *   (will be set up automatically on tables)
   *
   * Example usage:
   *  (table with one column thats only checkboxes)
   */

  var CHECK_ALL_UTIL_NAME = 'checkAll';
  var CHECK_ALL_UTIL_SELECTOR = 'table';

  var CHECKBOX_SELECTOR    = '[type="checkbox"]';

  var CHECK_ALL_INITIALIZED_CLASS = 'check-all--initialized';

  var checkAllUtil = function(element) {
    var columns = [];
    var checkboxColumn = [];
    var checkAllCheckbox = null;

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

      gatherColumns();
      setupCheckAllCheckbox();

      // mark initialized
      element.classList.add(CHECK_ALL_INITIALIZED_CLASS);

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

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

    function gatherColumns(tble) {
      var rows = Array.from(element.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);
        });
      });
      columns = 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() {
      var checkboxColumnId = findCheckboxColumn(columns);
      if (checkboxColumnId === null) {
        return;
      }

      checkboxColumn = columns[checkboxColumnId];
      var firstRow = element.querySelector('tr');
      var th = Array.from(firstRow.querySelectorAll('th, td'))[checkboxColumnId];
      checkAllCheckbox = document.createElement('input');
      checkAllCheckbox.setAttribute('type', 'checkbox');
      checkAllCheckbox.setAttribute('id', getCheckboxId());
      th.insertBefore(checkAllCheckbox, th.firstChild);

      // manually set up new checkbox
      if (UtilRegistry) {
        UtilRegistry.setup(UtilRegistry.find('checkbox'), th);
      }

      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.every(function(cell) {
        return cell.querySelector(CHECKBOX_SELECTOR).checked;
      })
      checkAllCheckbox.checked = allChecked;
    }

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

    return init();
  };

  // register check all checkbox util
  if (UtilRegistry) {
    UtilRegistry.register({
      name: CHECK_ALL_UTIL_NAME,
      selector: CHECK_ALL_UTIL_SELECTOR,
      setup: checkAllUtil
    });
  }
})();
