import { Utility } from '../../core/utility';

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

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

@Utility({
  selector: 'table',
})
export class CheckAll {

  _element;
  _app;

  _columns = [];
  _checkboxColumn = [];
  _checkAllCheckbox = null;

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

    this._element = element;
    this._app = app;

    if (this._element.classList.contains(CHECK_ALL_INITIALIZED_CLASS)) {
      return false;
    }

    this._gatherColumns();
    this._setupCheckAllCheckbox();

    // mark initialized
    this._element.classList.add(CHECK_ALL_INITIALIZED_CLASS);
  }

  destroy() {
    this._checkAllCheckbox.destroy();
  }

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

  _gatherColumns() {
    const rows = Array.from(this._element.querySelectorAll('tr'));
    const cols = [];
    rows.forEach((tr) => {
      const cells = Array.from(tr.querySelectorAll('td'));
      cells.forEach((cell, cellIndex) => {
        if (!cols[cellIndex]) {
          cols[cellIndex] = [];
        }
        cols[cellIndex].push(cell);
      });
    });
    this._columns = cols;
  }

  _findCheckboxColumn(columns) {
    let checkboxColumnId = null;
    columns.forEach((col, i) => {
      if (this._isCheckboxColumn(col)) {
        checkboxColumnId = i;
      }
    });
    return checkboxColumnId;
  }

  _isCheckboxColumn(col) {
    let onlyCheckboxes = true;
    col.forEach((cell) => {
      if (onlyCheckboxes && !cell.querySelector(CHECKBOX_SELECTOR)) {
        onlyCheckboxes = false;
      }
    });
    return onlyCheckboxes;
  }

  _setupCheckAllCheckbox() {
    const checkboxColumnId = this._findCheckboxColumn(this._columns);
    if (checkboxColumnId === null) {
      return;
    }

    this._checkboxColumn = this._columns[checkboxColumnId];
    const firstRow = this._element.querySelector('tr');
    const th = Array.from(firstRow.querySelectorAll('th, td'))[checkboxColumnId];
    this._checkAllCheckbox = document.createElement('input');
    this._checkAllCheckbox.setAttribute('type', 'checkbox');
    this._checkAllCheckbox.setAttribute('id', this._getCheckboxId());
    th.insertBefore(this._checkAllCheckbox, th.firstChild);

    // set up new checkbox
    this._app.utilRegistry.setupAll(th);

    this._checkAllCheckbox.addEventListener('input', () => this._onCheckAllCheckboxInput());
    this._setupCheckboxListeners();
  }

  _onCheckAllCheckboxInput() {
    this._toggleAll(this._checkAllCheckbox.checked);
  }

  _setupCheckboxListeners() {
    this._checkboxColumn.map((cell) => {
        return cell.querySelector(CHECKBOX_SELECTOR);
      })
      .forEach((checkbox) => {
        checkbox.addEventListener('input', () => this._updateCheckAllCheckboxState());
      });
  }

  _updateCheckAllCheckboxState() {
    const allChecked = this._checkboxColumn.every((cell) => {
      return cell.querySelector(CHECKBOX_SELECTOR).checked;
    });
    this._checkAllCheckbox.checked = allChecked;
  }

  _toggleAll(checked) {
    this._checkboxColumn.forEach((cell) => {
      cell.querySelector(CHECKBOX_SELECTOR).checked = checked;
    });
  }
}
