// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as constant from '../src/constants';
import { State } from '../src/state';
import { LogField } from '../src/fields';

export class LogHeader {
  private tableHeader: Element;
  private maxWidths = {} as Record<string, number>;

  constructor(private state: State) {
    const fields = this.state.currentFields;
    const keys = Object.keys(fields);
    this.tableHeader = this.initTableHeader();
    for (let i = 0; i < keys.length; i++) {
      const header = keys[i] as LogField;
      const headerCell = document.createElement('div');
      this.maxWidths[header] = 0;
      headerCell.id = header;
      headerCell.style.width = fields[header].width;
      headerCell.innerText = fields[header].displayName;
      this.tableHeader.appendChild(headerCell);
      if (i === keys.length - 1) {
        break;
      }
      const headerDiv = document.createElement('div');
      headerDiv.classList.add('column-resize');
      headerCell.appendChild(headerDiv);
      createResizableColumn(this.state, this.maxWidths, headerCell, headerDiv);
    }
  }

  /**
   * Returns the core element.
   */
  get element() {
    return this.tableHeader;
  }

  /**
   * Initializes the header element.
   *
   * @return the header element.
   */
  private initTableHeader(): HTMLDivElement {
    const tableHeader = document.createElement('div');
    tableHeader.id = 'logs-table-header';
    return tableHeader;
  }

  public setMaxCellWidth(id: LogField, maxWidth: number): void {
    this.maxWidths[id] = maxWidth;
  };
}

/**
 * Creates resizable element in header to determine column size.
 * @param header identify which header is active.
 * @param cell header cell of the column.
 * @param resizer element in the header cell that handles the resizing.
 */
function createResizableColumn(state: State, maxWidths: Record<string, number>,
  cell: HTMLElement, resizer: HTMLElement) {

  let header = cell.id as LogField;
  let w = 0;
  let x = 0;

  const mouseDoubleClickHandler = function () {
    cell.style.width = `${maxWidths[header]}px`;
    state.setHeaderWidth(header, cell.style.width);
  };

  const mouseDownHandler = function (e: MouseEvent) {
    x = e.clientX;
    w = cell.clientWidth;

    document.addEventListener('mousemove', mouseMoveHandler);
    document.addEventListener('mouseup', mouseUpHandler);

    resizer.classList.add('resizing');
  };

  const mouseMoveHandler = function (e: MouseEvent) {
    const dx = e.clientX - x;
    if ((w + dx) > constant.COL_MINWIDTH) {
      cell.style.width = `${w + dx}px`;
      state.setHeaderWidth(header, cell.style.width);
    }
  };

  const mouseUpHandler = function () {
    resizer.classList.remove('resizing');
    document.removeEventListener('mousemove', mouseMoveHandler);
    document.removeEventListener('mouseup', mouseUpHandler);
  };

  resizer.addEventListener('mousedown', mouseDownHandler);
  resizer.addEventListener('dblclick', mouseDoubleClickHandler);
}

