/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {Listener, Phase} from "./tobago-listener";
import {DomUtils} from "./tobago-utils";
import {CommandHelper} from "./tobago-command";
import {Page} from "./tobago-page";

class Sheet {

  static readonly SHEETS: Map<string, Sheet> = new Map<string, Sheet>();
  static readonly SCROLL_BAR_SIZE: number = Sheet.getScrollBarSize();

  id: string;

  clickActionId: string;
  clickReloadComponentId: string;
  dblClickActionId: string;
  dblClickReloadComponentId: string;

  mousemoveData: any;
  mousedownOnRowData: any;

  static init(element: HTMLElement): void {
    console.time("[tobago-sheet] init");
    for (const sheetElement of DomUtils.selfOrElementsByClassName(element, "tobago-sheet")) {
      const sheet = new Sheet(sheetElement);
      Sheet.SHEETS.set(sheet.id, sheet);
    }
    console.timeEnd("[tobago-sheet] init");
  }

  private static getScrollBarSize(): number {
    const body = document.getElementsByTagName("body").item(0);

    const outer = document.createElement("div");
    outer.style.visibility = "hidden";
    outer.style.width = "100px";
    outer.style.overflow = "scroll";
    body.append(outer);

    const inner = document.createElement("div");
    inner.style.width = "100%";
    outer.append(inner);
    const widthWithScroll = inner.offsetWidth;

    body.removeChild(outer);

    return 100 - widthWithScroll;
  }

  private static isInputElement(element: HTMLElement): boolean {
    return ["INPUT", "TEXTAREA", "SELECT", "A", "BUTTON"].indexOf(element.tagName) > -1;
  }

  constructor(element: HTMLElement) {
    this.id = element.id;
    const commands = element.dataset.tobagoRowAction;
    const behavior = element.dataset.tobagoBehaviorCommands;
    this.clickActionId = null;//todo commands.click.action;
    this.clickReloadComponentId = null;//todo commands.click.partially; // fixme: partially no longer used?
    this.dblClickActionId = null;//todo commands.dblclick.action;
    this.dblClickReloadComponentId = null;//todo commands.dblclick.partially;// fixme: partially no longer used?

    // synchronize column widths ----------------------------------------------------------------------------------- //

    // basic idea: there are two possible sources for the sizes:
    // 1. the columns attribute of <tc:sheet> like {"columns":[1.0,1.0,1.0]}, held by data attribute "tobago-layout"
    // 2. the hidden field which may contain a value like ",300,200,100,"
    //
    // The 1st source usually is the default set by the developer.
    // The 2nd source usually is the value set by the user manipulating the column widths.
    //
    // So, if the 2nd is set, we use it, if not set, we use the 1st source.

    let columnWidths = this.loadColumnWidths();
    console.info("columnWidths: " + columnWidths);
    if (columnWidths && columnWidths.length === 0) { // active, but empty
      // otherwise use the layout definition
      const tokens = JSON.parse(element.dataset.tobagoLayout).columns;
      const columnRendered = this.isColumnRendered();

      const headerCols = this.getHeaderCols();
      const bodyTable = this.getBodyTable();
      const bodyCols = this.getBodyCols();

      console.assert(headerCols.length - 1 === bodyCols.length, "header and body column number doesn't match");

      let sumRelative = 0; // tbd: is this needed?
      let widthRelative = bodyTable.offsetWidth;
      for (let i = 0; i < tokens.length; i++) {
        if (columnRendered[i]) {
          if (typeof tokens[i] === "number") {
            sumRelative += tokens[i];
          } else if (typeof tokens[i] === "object" && tokens[i].measure !== undefined) {
            const intValue = parseInt(tokens[i].measure);
            if (tokens[i].measure.lastIndexOf("px") > 0) {
              widthRelative -= intValue;
            } else if (tokens[i].measure.lastIndexOf("%") > 0) {
              widthRelative -= bodyTable.offsetWidth * intValue / 100;
            }
          } else {
            console.debug("auto? = " + tokens[i]);
          }
        }
      }
      if (widthRelative < 0) {
        widthRelative = 0;
      }

      let headerBodyColCount = 0;
      for (let i = 0; i < tokens.length; i++) {
        let colWidth = 0;
        if (columnRendered[i]) {
          if (typeof tokens[i] === "number") {
            colWidth = tokens[i] * widthRelative / sumRelative;
          } else if (typeof tokens[i] === "object" && tokens[i].measure !== undefined) {
            const intValue = parseInt(tokens[i].measure);
            if (tokens[i].measure.lastIndexOf("px") > 0) {
              colWidth = intValue;
            } else if (tokens[i].measure.lastIndexOf("%") > 0) {
              colWidth = bodyTable.offsetWidth * intValue / 100;
            }
          } else {
            console.debug("auto? = " + tokens[i]);
          }
          if (colWidth > 0) { // because tokens[i] == "auto"
            headerCols.item(headerBodyColCount).setAttribute("width", String(colWidth));
            bodyCols.item(headerBodyColCount).setAttribute("width", String(colWidth));
          }
          headerBodyColCount++;
        }
      }
    }
    this.addHeaderFillerWidth();

    // resize column: mouse events -------------------------------------------------------------------------------- //

    for (const resizeElement of <NodeListOf<HTMLElement>>element.querySelectorAll(".tobago-sheet-headerResize")) {
      resizeElement.addEventListener("click", function (): boolean {
        return false;
      });
      resizeElement.addEventListener("mousedown", this.mousedown.bind(this));
    }

    // scrolling -------------------------------------------------------------------------------------------------- //
    const sheetBody = this.getBody();

    // restore scroll position
    const value: number[] = JSON.parse(this.getHiddenScrollPosition().getAttribute("value"));
    sheetBody.scrollLeft = value[0];
    sheetBody.scrollTop = value[1];

    this.syncScrolling();

    // scroll events
    sheetBody.addEventListener("scroll", this.scroll.bind(this));

    // add selection listeners ------------------------------------------------------------------------------------ //
    const selectionMode = element.dataset.tobagoSelectionMode;
    if (selectionMode === "single" || selectionMode === "singleOrNone" || selectionMode === "multi") {

      for (const row of this.getRows()) {
        row.addEventListener("mousedown", this.mousedownOnRow.bind(this));

        row.addEventListener("click", this.clickOnRow.bind(this));

        // todo: check if this works correctly
        const sheet = Sheet.SHEETS.get(this.id);
        if (sheet && sheet.dblClickActionId) {
          row.addEventListener("dblclick", function (event: Event): void {
            // todo: re-implement
            sheet.doDblClick(event);
          });
        }
      }
    }

    for (const checkbox of <NodeListOf<HTMLInputElement>>element.querySelectorAll(
        ".tobago-sheet-cell > input.tobago-sheet-columnSelector")) {
      checkbox.addEventListener("click", (event) => {
        event.preventDefault();
      });
    }

    // ---------------------------------------------------------------------------------------- //

    for (const checkbox of <NodeListOf<HTMLInputElement>>element.querySelectorAll(
        ".tobago-sheet-header .tobago-sheet-columnSelector")) {
      checkbox.addEventListener("click", this.clickOnCheckbox.bind(this));
    }

    // init paging by pages ---------------------------------------------------------------------------------------- //

    for (const pagingText of <NodeListOf<HTMLElement>>element.querySelectorAll(".tobago-sheet-pagingText")) {

      pagingText.addEventListener("click", this.clickOnPaging.bind(this));

      const pagingInput = pagingText.querySelector("input.tobago-sheet-pagingInput");
      pagingInput.addEventListener("blur", this.blurPaging.bind(this));

      pagingInput.addEventListener("keydown", function (event: KeyboardEvent): void {
        if (event.keyCode === 13) {
          event.stopPropagation();
          event.preventDefault();
          event.currentTarget.dispatchEvent(new Event("blur"));
        }
      });
    }

  }

  loadColumnWidths(): number[] {
    const hidden = document.getElementById(this.id + DomUtils.SUB_COMPONENT_SEP + "widths");
    if (hidden) {
      return JSON.parse(hidden.getAttribute("value"));
    } else {
      return undefined;
    }
  }

  saveColumnWidths(widths: number[]): void {
    const hidden = document.getElementById(this.id + DomUtils.SUB_COMPONENT_SEP + "widths");
    if (hidden) {
      hidden.setAttribute("value", JSON.stringify(widths));
    } else {
      console.warn("ignored, should not be called, id='" + this.id + "'");
    }
  }

  getElement(): HTMLElement {
    return document.getElementById(this.id);
  }

  isColumnRendered(): boolean[] {
    const hidden = document.getElementById(this.id + DomUtils.SUB_COMPONENT_SEP + "rendered");
    return JSON.parse(hidden.getAttribute("value"));
  }

  addHeaderFillerWidth(): void {
    const last = document.getElementById(this.id).querySelector(".tobago-sheet-headerTable col:last-child");
    if (last) {
      last.setAttribute("width", String(Sheet.SCROLL_BAR_SIZE));
    }
  }

  mousedown(event: MouseEvent): void {

    Page.page().dataset.SheetMousedownData = this.id;

    // begin resizing
    console.debug("down");

    const resizeElement = event.currentTarget as HTMLElement;
    const columnIndex = parseInt(resizeElement.dataset.tobagoColumnIndex);
    const headerColumn = this.getHeaderCols().item(columnIndex);
    const mousemoveListener = this.mousemove.bind(this);
    const mouseupListener = this.mouseup.bind(this);
    this.mousemoveData = {
      columnIndex: columnIndex,
      originalClientX: event.clientX,
      originalHeaderColumnWidth: parseInt(headerColumn.getAttribute("width")),
      mousemoveListener: mousemoveListener,
      mouseupListener: mouseupListener
    };

    document.addEventListener("mousemove", mousemoveListener);
    document.addEventListener("mouseup", mouseupListener);
  }

  mousemove(event: MouseEvent): boolean {
    console.debug("move");
    let delta = event.clientX - this.mousemoveData.originalClientX;
    delta = -Math.min(-delta, this.mousemoveData.originalHeaderColumnWidth - 10);
    let columnWidth = this.mousemoveData.originalHeaderColumnWidth + delta;
    this.getHeaderCols().item(this.mousemoveData.columnIndex).setAttribute("width", columnWidth);
    this.getBodyCols().item(this.mousemoveData.columnIndex).setAttribute("width", columnWidth);
    if (window.getSelection) {
      window.getSelection().removeAllRanges();
    }
    return false;
  }

  mouseup(event: MouseEvent): boolean {
    console.debug("up");

    // switch off the mouse move listener
    document.removeEventListener("mousemove", this.mousemoveData.mousemoveListener);
    document.removeEventListener("mouseup", this.mousemoveData.mouseupListener);
    // copy the width values from the header to the body, (and build a list of it)
    const tokens = JSON.parse(this.getElement().dataset.tobagoLayout).columns;
    const columnRendered = this.isColumnRendered();
    const columnWidths = this.loadColumnWidths();

    const bodyTable = this.getBodyTable();
    const headerCols = this.getHeaderCols();
    const bodyCols = this.getBodyCols();
    const widths: number[] = [];
    let usedWidth = 0;
    let headerBodyColCount = 0;
    for (let i = 0; i < columnRendered.length; i++) {
      if (columnRendered[i]) {
        // last column is the filler column
        const newWidth = parseInt(headerCols.item(headerBodyColCount).getAttribute("width"));
        // for the hidden field
        widths[i] = newWidth;
        usedWidth += newWidth;

        const oldWidth = parseInt(bodyCols.item(headerBodyColCount).getAttribute("width"));
        if (oldWidth !== newWidth) {
          bodyCols.item(headerBodyColCount).setAttribute("width", String(newWidth));
        }
        headerBodyColCount++;
      } else if (columnWidths !== undefined && columnWidths.length >= i) {
        widths[i] = columnWidths[i];
      } else {
        if (typeof tokens[i] === "number") {
          widths[i] = 100;
        } else if (typeof tokens[i] === "object" && tokens[i].measure !== undefined) {
          const intValue = parseInt(tokens[i].measure);
          if (tokens[i].measure.lastIndexOf("px") > 0) {
            widths[i] = intValue;
          } else if (tokens[i].measure.lastIndexOf("%") > 0) {
            widths[i] = parseInt(bodyTable.style.width) / 100 * intValue;
          }
        }
      }
    }

    // store the width values in a hidden field
    this.saveColumnWidths(widths);
    return false;
  }

  scroll(event): void {
    console.debug("scroll");

    const sheetBody: HTMLElement = event.currentTarget;

    this.syncScrolling();

    // store the position in a hidden field
    const hidden = this.getHiddenScrollPosition();
    hidden.setAttribute("value",
        JSON.stringify([Math.round(sheetBody.scrollLeft), Math.round(sheetBody.scrollTop)]));
  }

  mousedownOnRow(event: MouseEvent): void {
    console.debug("mousedownOnRow");
    this.mousedownOnRowData = {
      x: event.clientX,
      y: event.clientY
    };
  }

  clickOnCheckbox(event: MouseEvent): void {
    const checkbox = event.currentTarget as HTMLInputElement;
    if (checkbox.checked) {
      this.selectAll();
    } else {
      this.deselectAll();
    }
  }

  clickOnRow(event: MouseEvent): void {

    const row = event.currentTarget as HTMLTableRowElement;
    if (row.classList.contains("tobago-sheet-columnSelector") || !Sheet.isInputElement(row)) {
      const sheet = this.getElement();

      if (Math.abs(this.mousedownOnRowData.x - event.clientX)
          + Math.abs(this.mousedownOnRowData.y - event.clientY) > 5) {
        // The user has moved the mouse. We assume, the user want to select some text inside the sheet,
        // so we doesn't select the row.
        return;
      }

      if (window.getSelection) {
        window.getSelection().removeAllRanges();
      }

      const rows = this.getRows();
      const selector = this.getSelectorCheckbox(row);
      const selectionMode = this.getElement().dataset.tobagoSelectionMode;

      if ((!event.ctrlKey && !event.metaKey && !selector)
          || selectionMode === "single" || selectionMode === "singleOrNone") {
        this.deselectAll();
        this.resetSelected();
      }

      const lastClickedRowIndex = parseInt(sheet.dataset.tobagoLastClickedRowIndex);
      if (event.shiftKey && selectionMode === "multi" && lastClickedRowIndex > -1) {
        if (lastClickedRowIndex <= row.sectionRowIndex) {
          this.selectRange(rows, lastClickedRowIndex, row.sectionRowIndex, true, false);
        } else {
          this.selectRange(rows, row.sectionRowIndex, lastClickedRowIndex, true, false);
        }
      } else if (selectionMode !== "singleOrNone" || !this.isRowSelected(row)) {
        this.toggleSelection(row, selector);
      }
      const rowAction = sheet.dataset.tobagoRowAction;
      const commands = rowAction ? JSON.parse(rowAction) : undefined;
      const click = commands ? commands.click : undefined;
      const clickActionId = click ? click.action : undefined;
      const clickExecuteIds = click ? click.execute : undefined;
      const clickRenderIds = click ? click.render : undefined;

      if (clickActionId) {
        let action: string;
        const index = clickActionId.indexOf(sheet.id);
        const rowIndex = this.getDataIndex(row);
        if (index >= 0) {
          action = sheet.id + ":" + rowIndex + ":" + clickActionId.substring(index + sheet.id.length + 1);
        } else {
          action = sheet.id + ":" + rowIndex + ":" + clickActionId;
        }
        if (clickExecuteIds && clickExecuteIds.length > 0) {
          jsf.ajax.request(
              action,
              event,
              {
                //"javax.faces.behavior.event": "click",
                execute: clickExecuteIds,
                render: clickRenderIds
              });
        } else {
          CommandHelper.submitAction(row, action);
        }
      }
    }
  }

  clickOnPaging(event: MouseEvent): void {
    const element = event.currentTarget as HTMLElement;

    const output = element.querySelector(".tobago-sheet-pagingOutput") as HTMLElement;
    output.style.display = "none";

    const input = element.querySelector(".tobago-sheet-pagingInput") as HTMLInputElement;
    input.style.display = "initial";
    input.focus();
    input.select();
  }

  blurPaging(event: FocusEvent): void {
    const input = event.currentTarget as HTMLInputElement;
    const output = input.parentElement.querySelector(".tobago-sheet-pagingOutput") as HTMLElement;
    if (output.innerHTML !== input.value) {
      console.debug(
          "Reloading sheet '" + this.id + "' old value='" + output.innerHTML + "' new value='" + input.value + "'");
      output.innerHTML = input.value;
      jsf.ajax.request(
          input.id,
          null,
          {
            "javax.faces.behavior.event": "reload",
            execute: this.id,
            render: this.id
          });
    } else {
      console.info("no update needed");
      input.style.display = "none";
      output.style.display = "initial";
    }
  }

  syncScrolling(): void {
    // sync scrolling of body to header
    const header = this.getHeader();
    if (header) {
      header.scrollLeft = this.getBody().scrollLeft;
    }
  }

  getHeader(): HTMLElement {
    return this.getElement().querySelector(".tobago-sheet>header");
  }

  getHeaderTable(): HTMLElement {
    return this.getElement().querySelector(".tobago-sheet>header>table");
  }

  getHeaderCols(): NodeListOf<HTMLElement> {
    return this.getElement().querySelectorAll(".tobago-sheet>header>table>colgroup>col");
  }

  getBody(): HTMLElement {
    return this.getElement().querySelector(".tobago-sheet>.tobago-sheet-body");
  }

  getBodyTable(): HTMLElement {
    return this.getElement().querySelector(".tobago-sheet>.tobago-sheet-body>.tobago-sheet-bodyTable");
  }

  getBodyCols(): NodeListOf<HTMLElement> {
    return this.getElement().querySelectorAll(".tobago-sheet>.tobago-sheet-body>.tobago-sheet-bodyTable>colgroup>col");
  }

  getHiddenSelected(): HTMLInputElement {
    return document.getElementById(this.id + DomUtils.SUB_COMPONENT_SEP + "selected") as HTMLInputElement;
  }

  getHiddenScrollPosition(): HTMLInputElement {
    return document.getElementById(this.id + DomUtils.SUB_COMPONENT_SEP + "scrollPosition") as HTMLInputElement;
  }

  doDblClick(event): void {
    const row = event.currentTarget as HTMLTableRowElement;
    const rowIndex = row.sectionRowIndex + this.getFirst();
    if (this.dblClickActionId) {
      let action;
      const index = this.dblClickActionId.indexOf(this.id);
      if (index >= 0) {
        action = this.id + ":" + rowIndex + ":" + this.dblClickActionId.substring(index + this.id.length + 1);
      } else {
        action = this.id + ":" + rowIndex + ":" + this.dblClickActionId;
      }
      if (this.dblClickReloadComponentId && this.dblClickReloadComponentId.length > 0) {
        jsf.ajax.request(
            action,
            event,
            {
              //"javax.faces.behavior.event": "dblclick",
              execute: this.dblClickReloadComponentId,
              render: this.dblClickReloadComponentId
            });
      } else {
        CommandHelper.submitAction(row, action);
      }
    }
  }

  /**
   * Get the element, which indicates the selection
   */
  getSelectorCheckbox(row): HTMLInputElement {
    return row.querySelector("tr>td>input.tobago-sheet-columnSelector");
  }

  getRows(): NodeListOf<HTMLTableRowElement> {
    return this.getBodyTable().querySelectorAll("tbody>tr");
  }

  getFirst(): number {
    return parseInt(this.getElement().dataset.tobagoFirst);
  }

  isRowSelected(row: HTMLTableRowElement): boolean {
    let rowIndex = +row.dataset.tobagoRowIndex;
    if (!rowIndex) {
      rowIndex = row.sectionRowIndex + this.getFirst();
    }
    return this.isSelected(rowIndex);
  }

  isSelected(rowIndex: number): boolean {
    const value = <number[]>JSON.parse(this.getHiddenSelected().value);
    return value.indexOf(rowIndex) > -1;
  }

  resetSelected():void {
    this.getHiddenSelected().value = JSON.stringify([]);
  }

  toggleSelection(row: HTMLTableRowElement, checkbox: HTMLInputElement): void {
    this.getElement().dataset.tobagoLastClickedRowIndex = String(row.sectionRowIndex);
    if (checkbox && !checkbox.disabled) {
      const selected = this.getHiddenSelected();
      const rowIndex = this.getDataIndex(row);
      if (this.isSelected(rowIndex)) {
        this.deselectRow(selected, rowIndex, row, checkbox);
      } else {
        this.selectRow(selected, rowIndex, row, checkbox);
      }
    }
  }

  selectAll(): void {
    const rows = this.getRows();
    this.selectRange(rows, 0, rows.length - 1, true, false);
  }

  deselectAll(): void {
    const rows = this.getRows();
    this.selectRange(rows, 0, rows.length - 1, false, true);
  }

  toggleAll(): void {
    const rows = this.getRows();
    this.selectRange(rows, 0, rows.length - 1, true, true);
  }

  selectRange(
      rows: NodeListOf<HTMLTableRowElement>, first: number, last: number, selectDeselected: boolean,
      deselectSelected: boolean): void {
    const selected = this.getHiddenSelected();
    const value = new Set<number>(JSON.parse(selected.value));
    for (let i = first; i <= last; i++) {
      const row = rows.item(i);
      const checkbox = this.getSelectorCheckbox(row);
      if (checkbox && !checkbox.disabled) {
        const rowIndex = this.getDataIndex(row);
        const on = value.has(rowIndex);
        if (selectDeselected && !on) {
          this.selectRow(selected, rowIndex, row, checkbox);
        } else if (deselectSelected && on) {
          this.deselectRow(selected, rowIndex, row, checkbox);
        }
      }
    }
  }

  getDataIndex(row: HTMLTableRowElement): number {
    const rowIndex = parseInt(row.dataset.tobagoRowIndex);
    if (rowIndex) {
      return rowIndex;
    } else {
      return row.sectionRowIndex + this.getFirst();
    }
  }

  /**
   * @param selected input-element type=hidden: Hidden field with the selection state information
   * @param rowIndex int: zero based index of the row.
   * @param row tr-element: the row.
   * @param checkbox input-element: selector in the row.
   */
  selectRow(selected: HTMLInputElement, rowIndex: number, row: HTMLTableRowElement, checkbox: HTMLInputElement): void {
    const selectedSet = new Set<number>(JSON.parse(selected.value));
    selected.value = JSON.stringify(Array.from(selectedSet.add(rowIndex)));
    row.classList.add("tobago-sheet-row-markup-selected");
    row.classList.add("table-info");
    checkbox.checked = true;
    setTimeout(function ():void {
      checkbox.checked = true;
    }, 0);
  }

  /**
   * @param selected input-element type=hidden: Hidden field with the selection state information
   * @param rowIndex int: zero based index of the row.
   * @param row tr-element: the row.
   * @param checkbox input-element: selector in the row.
   */
  deselectRow(
      selected: HTMLInputElement, rowIndex: number, row: HTMLTableRowElement, checkbox: HTMLInputElement): void {
    const selectedSet = new Set<number>(JSON.parse(selected.value));
    selectedSet.delete(rowIndex);
    selected.value = JSON.stringify(Array.from(selectedSet));
    row.classList.remove("tobago-sheet-row-markup-selected");
    row.classList.remove("table-info");
    checkbox.checked = false;
    // XXX check if this is still needed... Async because of TOBAGO-1312
    setTimeout(function (): void {
      checkbox.checked = false;
    }, 0);
  }

}

Listener.register(Sheet.init, Phase.DOCUMENT_READY);
Listener.register(Sheet.init, Phase.AFTER_UPDATE);
