// 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 } from '../src/fields';
import { FilterExpression } from '../src/filter';
import { State } from '../src/state';
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;
}

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

log-view: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 filterResultsCount: number = 0;

  constructor(private state: State) {
    super();
    this.maxWidths = new Array(Object.keys(state.currentFields).length).fill(0);
    this.logHeader = new LogHeader(state);
    this.logWrapping = state.shouldWrapLogs;
    this.ariaColCount = `${Object.keys(state.currentFields).length}`;

    state.addEventListener('filterChange', (e) => {
      const event = e as CustomEvent;
      const filter: FilterExpression = event.detail.filter;
      this.ariaColCount = `${this.logRows.length}`;
      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) {
    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.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.state.currentFilter.accepts(el);
  }
}
