// 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 {html, LitElement, css} from 'lit';
import {customElement, state} from 'lit/decorators.js';
import * as constant from '../src/constants';
import { LogHeader } from './log_header';
import { LogRow } from './log_row';
import {LogRowData} from '../src/log_data';
import {
  LogField,
  LogHeadersData,
  LogViewOptions,
  HeaderWidthChangeHandler
} from '../src/fields';
import {FilterExpression} from '../src/filter';
import * as styles from './styles';

export const WRAP_LOG_TEXT_ATTR = 'wrap-log-text';

const logStyles = css`
log-header>div {
  background-color: var(--vscode-editor-background);
  border-bottom: 2px solid var(--vscode-panel-border);
  padding-bottom: 5px;
  position: sticky;
  top: 0;
}

log-header,
log-view-row {
  display: table-row-group;
}

log-view-row[hidden] {
  display: none;
}

log-view-row>div {
  display: table-row;
}

.log-list-cell,
log-header>div {
  overflow: clip;
  text-align: left;
  text-overflow: ellipsis;
  vertical-align: top;
  white-space: nowrap;
  display: table-cell;
}

td#moniker {
  direction: rtl;
}

:host([wrap-log-text]) .msg-cell,
:host(:not([wrap-log-text])) .msg-cell:hover {
  text-overflow: clip;
  white-space: normal;
}

:host(:not([wrap-log-text])) .msg-cell:hover {
  background: var(--vscode-list-hoverBackground);
}


:host {
  display: table;
  table-layout: fixed;
  width: 100%;
  word-wrap: normal;
}

log-view-row {
  font-family: var(--vscode-editor-font-family);
  font-size: var(--vscode-editor-font-size);
  font-weight: var(--vscode-editor-font-weight);
}

log-view-row div[data-severity="warn"] {
  color: var(--vscode-list-warningForeground);
}

log-view-row div[data-severity="error"] {
  color: var(--vscode-list-errorForeground);
}

log-view-row div[data-moniker="<VSCode>"] {
  line-height: 75%;
  opacity: 70%;
}

.column-resize {
  cursor: col-resize;
  height: 100%;
  position: absolute;
  right: 0;
  top: 0;
  width: 5px;
}

.column-resize:hover,
.resizing {
  border-right: 2px solid var(--vscode-editor-foreground);
}`;

@customElement('log-view')
export class LogList extends LitElement {
  static styles = [
    styles.VSCODE_CSS,
    logStyles
  ];

  @state()
  private logRows: Array<LitElement> = [];
  private maxWidths: Array<number>;
  private logHeader: LogHeader;
  public lastTimestamp: number = 0;
  public filterResultsCount: number = 0;

  constructor(
    private headerFields: LogHeadersData,
    shouldWrapLogs: boolean,
    onHeaderWidthChange: HeaderWidthChangeHandler,
    private currentFilter: FilterExpression,
    private options: LogViewOptions) {
    super();
    this.maxWidths = new Array(Object.keys(headerFields).length).fill(0);
    this.logHeader = new LogHeader(headerFields, onHeaderWidthChange);
    this.logWrapping = shouldWrapLogs;
    this.ariaColCount = `${Object.keys(headerFields).length}`;
  }

  filterChangeHandler(event: CustomEvent) {
    const filter: FilterExpression = event.detail.filter;
    this.ariaColCount = `${this.logRows.length}`;
    this.currentFilter = filter;
    let resultCount = 0;

    if (filter.isEmpty()) {
      for (const element of this.logRows) {
        element.removeAttribute('hidden');
        resultCount++;
      }
    } else {
      for (const element of this.logRows) {
        if (filter.accepts(element.children[0])) {
          element.removeAttribute('hidden');
          resultCount++;
        } else {
          element.setAttribute('hidden', '');
        }
      }
    }

    this.filterResultsCount = resultCount;
  }

  render() {
    return html`
      ${this.logHeader}
      ${this.logRows}
    `;
  }

  /**
   * Defines whether or not to wrap the log text.
   *
   * @param logWrapActive if true the log text will be wrapped
   */
  public set logWrapping(logWrapActive: boolean) {
    if (logWrapActive) {
      this.setAttribute(WRAP_LOG_TEXT_ATTR, 'true');
    } else {
      this.removeAttribute(WRAP_LOG_TEXT_ATTR);
    }
  }

  /**
   * Appends a log to the current list of logs
   */
  public addLog(log: LogRowData) {
    const timestampField = log.timestamp;
    // Keep the timestamp around so we know when to start of from
    // when we clear logs.
    if (timestampField && timestampField > this.lastTimestamp) {
      // ffx does not guarantee that logs come in order
      // of timestamp.
      this.lastTimestamp = timestampField;
    }
    this.addLogElement(log);
  }

  /**
   * Resets the state and contents of the webview to contain nothing.
   * The persistent state is maintained as that represents user selections.
   */
  public reset() {
    this.logRows = [];
    this.filterResultsCount = 0;
  }

  private addLogElement(log: LogRowData) {
    const logsToDrop = this.logRows.length - constant.MAX_LOGS;
    for (let i = 0; i < logsToDrop; i++) {
      this.popLogElement();
    }
    this.appendLogElement(log);
  }

  private appendLogElement(log: LogRowData) {
    const element = new LogRow(
      log, this.headerFields, this.options.columnFormatter);
    this.logRows = [...this.logRows, element];
    element.updateComplete
      .then(() => {
        if (!this.filtersAllow(element.children[0])) {
          element.setAttribute('hidden', '');
        }
        this.setMaxCellWidth(element.children[0]);
        if (!this.parentElement?.matches(':hover')) {
          this.parentElement?.scrollTo(-1, this.scrollHeight);
        };
      })
      .catch(e => { });
  }

  private setMaxCellWidth(row: Element) {
    for (const cell in Array.from(row.children)) {
      let id = row.children[cell].id as LogField;
      let width = this.maxWidths[cell];
      if (width < row.children[cell].scrollWidth) {
        this.maxWidths[cell] = row.children[cell].scrollWidth;
        this.logHeader.setMaxCellWidth(id, this.maxWidths[cell]);
      }
    }
  }

  private popLogElement() {
    this.logRows = this.logRows.slice(1);
  }

  private filtersAllow(el: Element) {
    return this.currentFilter.accepts(el);
  }
}
