// SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

import { Utility } from '../../core/utility';
import { TableIndices } from '../../lib/table/table';
import { FrontendTooltips } from '../../lib/tooltips/frontend-tooltips';
import { Translations } from '../../messages';


const CHECKRANGE_INITIALIZED_CLASS = 'checkrange--initialized';
const CHECKBOX_SELECTOR = '[type="checkbox"]';


@Utility({
    selector: 'table:not([uw-no-check-all])',
  })
export class CheckRange {
    _lastCheckedCell = null;
    _element;
    _tableIndices;
    _columns = new Array();

    constructor(element) {
        if(!element) {
            throw new Error('Check Range Utility cannot be setup without an element');
        }

        this._element = element;

        if (this._element.classList.contains(CHECKRANGE_INITIALIZED_CLASS))
            return false;
        
        this._tableIndices = new TableIndices(this._element);

        this._gatherColumns();

        let checkboxColumns = this._findCheckboxColumns();

        checkboxColumns.forEach(columnId => this._setUpShiftClickOnColumn(columnId));

        this._element.classList.add(CHECKRANGE_INITIALIZED_CLASS);
    }

    _setUpShiftClickOnColumn(columnId) {
      if (!this._columns || columnId < 0 || columnId >= this._columns.length) return;
      let column = this._columns[columnId];
      let language = document.documentElement.lang;
      let toolTipMessage = Translations.getTranslation('checkrangeTooltip', language);
      FrontendTooltips.addToolTip(column[0], toolTipMessage);
      column.forEach(el => el.addEventListener('click', (ev) => {
  
        if(ev.shiftKey && this.lastCheckedCell !== null) {
          let lastClickedIndex = this._tableIndices.rowIndex(this._lastCheckedCell);
          let currentCellIndex = this._tableIndices.rowIndex(el);
          let cell = this._columns[columnId][currentCellIndex];
          if(currentCellIndex > lastClickedIndex)
            this._handleCellsInBetween(cell, lastClickedIndex, currentCellIndex, columnId);
          else
            this._handleCellsInBetween(cell, currentCellIndex, lastClickedIndex, columnId);
        } else {
          this._lastCheckedCell = el;
        }
      }));
    }

    _handleCellsInBetween(cell, firstRowIndex, lastRowIndex, columnId) {
      if(this._isChecked(cell)) {
        this._uncheckMultipleCells(firstRowIndex, lastRowIndex, columnId);
      } else {
        this._checkMultipleCells(firstRowIndex, lastRowIndex, columnId);
      }
    }

    _checkMultipleCells(firstRowIndex, lastRowIndex, columnId) {
      for(let i=firstRowIndex; i<=lastRowIndex; i++) {
        let cell = this._columns[columnId][i];
        if (cell.tagName !== 'TH') {
          cell.querySelector(CHECKBOX_SELECTOR).checked = true;
        }
      }
    }

    _uncheckMultipleCells(firstRowIndex, lastRowIndex, columnId) {
      for(let i=firstRowIndex; i<=lastRowIndex; i++) {
        let cell = this._columns[columnId][i];
        if (cell.tagName !== 'TH') {
          cell.querySelector(CHECKBOX_SELECTOR).checked = false;
        }
      }
    }

    _isChecked(cell) {
      return cell.querySelector(CHECKBOX_SELECTOR).checked;
    }


    _gatherColumns() {
        for (const rowIndex of Array(this._tableIndices.maxRow + 1).keys()) {
          for (const colIndex of Array(this._tableIndices.maxCol + 1).keys()) {
    
            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));
    }
}  