const DEBUG_MODE = /localhost/.test(window.location.href) ? 0 : 0;

import { Utility } from '../../core/utility';
import { TableIndices } from '../../lib/table/table';
import { EventManager, EventWrapper, EVENT_TYPE } from '../../lib/event-manager/event-manager';

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

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

@Utility({
  selector: 'table:not([uw-no-check-all])',
})
export class CheckAll {
  _element;

  _eventManager;

  _columns = new Array();
  _checkAllColumns = new Array();

  _tableIndices;

  _lastCheckedCell = null;

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

    this._element = element;

    this._eventManager = new EventManager();

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

    this._tableIndices = new TableIndices(this._element);

    this._gatherColumns();

    if (DEBUG_MODE > 0)
      console.log(this._columns);
    
    let checkboxColumns = this._findCheckboxColumns();

    checkboxColumns.forEach(columnId => this._checkAllColumns.push(new CheckAllColumn(this._element, app, this._columns[columnId])));

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

  destroy() {
    this._eventManager.cleanUp();
    this._checkAllColumns.forEach((column) => {
      if (column._checkAllCheckBox !== undefined)
        column._checkAllCheckBox.remove();
    });

    if(this._element.classList.contains(CHECK_ALL_INITIALIZED_CLASS))
      this._element.classList.remove(CHECK_ALL_INITIALIZED_CLASS);
  }

  _gatherColumns() {
    for (const rowIndex of Array(this._tableIndices.maxRow + 1).keys()) {
      for (const colIndex of Array(this._tableIndices.maxCol + 1).keys()) {
        if (DEBUG_MODE > 1)
          console.log(rowIndex, colIndex);

        const cell = this._tableIndices.getCell(rowIndex, colIndex);

        if (!cell)
          continue;
        
        if (!this._columns[colIndex])
          this._columns[colIndex] = new Array();

        this._columns[colIndex][rowIndex] = cell;
      }
    }
  }

  _findCheckboxColumns() {
    let checkboxColumnIds = new Array();
    this._columns.forEach((col, i) => {
      if (this._isCheckboxColumn(col)) {
        checkboxColumnIds.push(i);
      }
    });
    return checkboxColumnIds;
  }

  _isCheckboxColumn(col) {
    return col.every(cell => cell.tagName == 'TH' || cell.querySelector(CHECKBOX_SELECTOR))
      && col.some(cell => cell.querySelector(CHECKBOX_SELECTOR));
  }
}

class CheckAllColumn {
  _app;
  _table;
  _column;

  _eventManager
  
  _checkAllCheckbox;
  _checkboxId = 'check-all-checkbox-' + Math.floor(Math.random() * 100000);
  
  constructor(table, app, column, eventManager) {
    this._column = column;
    this._table = table;
    this._app = app;
    this._eventManager = eventManager;

    const th = this._column.filter(element => element.tagName == 'TH')[0];
    if (!th)
      return false;

    this._checkAllCheckbox = document.createElement('input');
    this._checkAllCheckbox.setAttribute('type', 'checkbox');
    this._checkAllCheckbox.setAttribute('id', this._checkboxId);

    th.insertBefore(this._checkAllCheckbox, th.firstChild);

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

    const checkBoxInputEvent = new EventWrapper(EVENT_TYPE.INPUT, this._onCheckAllCheckboxInput.bind(this), this._checkAllCheckbox);
    this._eventManager.registerNewListener(checkBoxInputEvent);  
    this._setupCheckboxListeners();
  }

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

  _setupCheckboxListeners() {
    this._column
      .flatMap(cell => cell.tagName == 'TH' ? new Array() : Array.from(cell.querySelectorAll(CHECKBOX_SELECTOR)))
      .forEach(checkbox => {
        const checkBoxUpdateEvent = new EventWrapper(EVENT_TYPE.INPUT, this._updateCheckAllCheckboxState.bind(this), checkbox);
        this._eventManager.registerNewListener(checkBoxUpdateEvent);
      });
  }

  _updateCheckAllCheckboxState() {
    const allChecked = this._column.every(cell =>
      cell.tagName == 'TH' || cell.querySelector(CHECKBOX_SELECTOR).checked
    );
    this._checkAllCheckbox.checked = allChecked;
  }

  _toggleAll(checked) {
    this._column.forEach(cell => {
      if (cell.tagName == 'TH')
        return;

      cell.querySelector(CHECKBOX_SELECTOR).checked = checked;
    });
  }
}
