/*
 * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

import * as Common from '../common/common.js';
import * as DataGrid from '../data_grid/data_grid.js';
import * as Host from '../host/host.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as SourceFrame from '../source_frame/source_frame.js';
import * as TextUtils from '../text_utils/text_utils.js';
import * as UI from '../ui/ui.js';

import {BinaryResourceView} from './BinaryResourceView.js';

/**
 * @unrestricted
 */
export class ResourceWebSocketFrameView extends UI.Widget.VBox {
  /**
   * @param {!SDK.NetworkRequest.NetworkRequest} request
   */
  constructor(request) {
    super();
    this.registerRequiredCSS('network/webSocketFrameView.css', {enableLegacyPatching: true});
    this.element.classList.add('websocket-frame-view');
    this._request = request;

    this._splitWidget = new UI.SplitWidget.SplitWidget(false, true, 'resourceWebSocketFrameSplitViewState');
    this._splitWidget.show(this.element);

    const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
      {id: 'data', title: Common.UIString.UIString('Data'), sortable: false, weight: 88}, {
        id: 'length',
        title: Common.UIString.UIString('Length'),
        sortable: false,
        align: DataGrid.DataGrid.Align.Right,
        weight: 5
      },
      {id: 'time', title: Common.UIString.UIString('Time'), sortable: true, weight: 7}
    ]);

    this._dataGrid = new DataGrid.SortableDataGrid.SortableDataGrid({
      displayName: ls`Web Socket Frame`,
      columns,
      editCallback: undefined,
      deleteCallback: undefined,
      refreshCallback: undefined
    });
    this._dataGrid.setRowContextMenuCallback(onRowContextMenu.bind(this));
    this._dataGrid.setStickToBottom(true);
    this._dataGrid.setCellClass('websocket-frame-view-td');
    this._timeComparator =
        /** @type {function(!DataGrid.SortableDataGrid.SortableDataGridNode<!ResourceWebSocketFrameNode>, !DataGrid.SortableDataGrid.SortableDataGridNode<!ResourceWebSocketFrameNode>):number} */
        (ResourceWebSocketFrameNodeTimeComparator);
    this._dataGrid.sortNodes(this._timeComparator, false);
    this._dataGrid.markColumnAsSortedBy('time', DataGrid.DataGrid.Order.Ascending);
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortItems, this);

    this._dataGrid.setName('ResourceWebSocketFrameView');
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode, event => {
      this._onFrameSelected(event);
    }, this);
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.DeselectedNode, this._onFrameDeselected, this);

    this._mainToolbar = new UI.Toolbar.Toolbar('');

    this._clearAllButton = new UI.Toolbar.ToolbarButton(Common.UIString.UIString('Clear All'), 'largeicon-clear');
    this._clearAllButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._clearFrames, this);
    this._mainToolbar.appendToolbarItem(this._clearAllButton);

    this._filterTypeCombobox = new UI.Toolbar.ToolbarComboBox(this._updateFilterSetting.bind(this), ls`Filter`);
    for (const filterItem of _filterTypes) {
      const option = this._filterTypeCombobox.createOption(filterItem.label, filterItem.name);
      this._filterTypeCombobox.addOption(option);
    }
    this._mainToolbar.appendToolbarItem(this._filterTypeCombobox);
    this._filterType = null;

    const placeholder = 'Enter regex, for example: (web)?socket';
    this._filterTextInput = new UI.Toolbar.ToolbarInput(Common.UIString.UIString(placeholder), '', 0.4);
    this._filterTextInput.addEventListener(UI.Toolbar.ToolbarInput.Event.TextChanged, this._updateFilterSetting, this);
    this._mainToolbar.appendToolbarItem(this._filterTextInput);
    this._filterRegex = null;

    const mainContainer = new UI.Widget.VBox();
    mainContainer.element.appendChild(this._mainToolbar.element);
    this._dataGrid.asWidget().show(mainContainer.element);
    mainContainer.setMinimumSize(0, 72);
    this._splitWidget.setMainWidget(mainContainer);

    this._frameEmptyWidget =
        new UI.EmptyWidget.EmptyWidget(Common.UIString.UIString('Select message to browse its content.'));
    this._splitWidget.setSidebarWidget(this._frameEmptyWidget);

    /** @type {?ResourceWebSocketFrameNode} */
    this._selectedNode = null;

    /**
     * @param {!UI.ContextMenu.ContextMenu} contextMenu
     * @param {!DataGrid.DataGrid.DataGridNode<?>} genericNode
     * @this {ResourceWebSocketFrameView}
     */
    function onRowContextMenu(contextMenu, genericNode) {
      const node = /** @type {!ResourceWebSocketFrameNode} */ (genericNode);
      const binaryView = node.binaryView();
      if (binaryView) {
        binaryView.addCopyToContextMenu(contextMenu, ls`Copy message...`);
      } else {
        contextMenu.clipboardSection().appendItem(
            Common.UIString.UIString('Copy message'),
            Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText.bind(
                Host.InspectorFrontendHost.InspectorFrontendHostInstance, node.data.data));
      }
      contextMenu.footerSection().appendItem(Common.UIString.UIString('Clear all'), this._clearFrames.bind(this));
    }
  }

  /**
   * @param {number} opCode
   * @param {boolean} mask
   * @return {string}
   */
  static opCodeDescription(opCode, mask) {
    const localizedDescription = opCodeDescriptions[opCode] || '';
    if (mask) {
      return ls`${localizedDescription} (Opcode ${opCode}, mask)`;
    }
    return ls`${localizedDescription} (Opcode ${opCode})`;
  }

  /**
   * @override
   */
  wasShown() {
    this.refresh();
    this._request.addEventListener(SDK.NetworkRequest.Events.WebsocketFrameAdded, this._frameAdded, this);
  }

  /**
   * @override
   */
  willHide() {
    this._request.removeEventListener(SDK.NetworkRequest.Events.WebsocketFrameAdded, this._frameAdded, this);
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _frameAdded(event) {
    const frame = /** @type {!SDK.NetworkRequest.WebSocketFrame} */ (event.data);
    if (!this._frameFilter(frame)) {
      return;
    }
    this._dataGrid.insertChild(new ResourceWebSocketFrameNode(this._request.url(), frame));
  }

  /**
   * @param {!SDK.NetworkRequest.WebSocketFrame} frame
   * @return {boolean}
   */
  _frameFilter(frame) {
    if (this._filterType && frame.type !== this._filterType) {
      return false;
    }
    return !this._filterRegex || this._filterRegex.test(frame.text);
  }

  _clearFrames() {
    // TODO(allada): actially remove frames from request.
    _clearFrameOffsets.set(this._request, this._request.frames().length);
    this.refresh();
  }

  _updateFilterSetting() {
    const text = this._filterTextInput.value();
    const type = /** @type {!HTMLOptionElement} */ (this._filterTypeCombobox.selectedOption()).value;
    this._filterRegex = text ? new RegExp(text, 'i') : null;
    this._filterType = type === 'all' ? null : type;
    this.refresh();
  }

  /**
  * @param {!Common.EventTarget.EventTargetEvent} event
   */
  async _onFrameSelected(event) {
    this._currentSelectedNode = /** @type {!ResourceWebSocketFrameNode} */ (event.data);
    const content = this._currentSelectedNode.dataText();

    const binaryView = this._currentSelectedNode.binaryView();
    if (binaryView) {
      this._splitWidget.setSidebarWidget(binaryView);
      return;
    }

    const jsonView = await SourceFrame.JSONView.JSONView.createView(content);
    if (jsonView) {
      this._splitWidget.setSidebarWidget(jsonView);
      return;
    }

    this._splitWidget.setSidebarWidget(new SourceFrame.ResourceSourceFrame.ResourceSourceFrame(
        TextUtils.StaticContentProvider.StaticContentProvider.fromString(
            this._request.url(), Common.ResourceType.resourceTypes.WebSocket, content)));
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _onFrameDeselected(event) {
    this._currentSelectedNode = null;
    this._splitWidget.setSidebarWidget(this._frameEmptyWidget);
  }

  refresh() {
    this._dataGrid.rootNode().removeChildren();

    const url = this._request.url();
    let frames = this._request.frames();
    const offset = _clearFrameOffsets.get(this._request) || 0;
    frames = frames.slice(offset);
    frames = frames.filter(this._frameFilter.bind(this));
    frames.forEach(frame => this._dataGrid.insertChild(new ResourceWebSocketFrameNode(url, frame)));
  }

  _sortItems() {
    this._dataGrid.sortNodes(this._timeComparator, !this._dataGrid.isSortOrderAscending());
  }
}

/** @enum {number} */
export const OpCodes = {
  ContinuationFrame: 0,
  TextFrame: 1,
  BinaryFrame: 2,
  ConnectionCloseFrame: 8,
  PingFrame: 9,
  PongFrame: 10
};

/** @type {!Array.<string> } */
export const opCodeDescriptions = (function() {
  const opCodes = OpCodes;
  const map = [];
  map[opCodes.ContinuationFrame] = ls`Continuation Frame`;
  map[opCodes.TextFrame] = ls`Text Message`;
  map[opCodes.BinaryFrame] = ls`Binary Message`;
  map[opCodes.ContinuationFrame] = ls`Connection Close Message`;
  map[opCodes.PingFrame] = ls`Ping Message`;
  map[opCodes.PongFrame] = ls`Pong Message`;
  return map;
})();

/** @type {!Array<!UI.FilterBar.Item>} */
export const _filterTypes = [
  {name: 'all', label: Common.UIString.UIString('All'), title: undefined},
  {name: 'send', label: Common.UIString.UIString('Send'), title: undefined},
  {name: 'receive', label: Common.UIString.UIString('Receive'), title: undefined},
];

/**
 * @unrestricted
 * @extends {DataGrid.SortableDataGrid.SortableDataGridNode<?>}
 */
export class ResourceWebSocketFrameNode extends DataGrid.SortableDataGrid.SortableDataGridNode {
  /**
   * @param {string} url
   * @param {!SDK.NetworkRequest.WebSocketFrame} frame
   */
  constructor(url, frame) {
    let length = String(frame.text.length);
    const time = new Date(frame.time * 1000);
    const timeText = ('0' + time.getHours()).substr(-2) + ':' + ('0' + time.getMinutes()).substr(-2) + ':' +
        ('0' + time.getSeconds()).substr(-2) + '.' + ('00' + time.getMilliseconds()).substr(-3);
    const timeNode = document.createElement('div');
    UI.UIUtils.createTextChild(timeNode, timeText);
    UI.Tooltip.Tooltip.install(timeNode, time.toLocaleString());

    let dataText = frame.text;
    let description = ResourceWebSocketFrameView.opCodeDescription(frame.opCode, frame.mask);
    const isTextFrame = frame.opCode === OpCodes.TextFrame;

    if (frame.type === SDK.NetworkRequest.WebSocketFrameType.Error) {
      description = dataText;
      length = ls`N/A`;

    } else if (isTextFrame) {
      description = dataText;

    } else if (frame.opCode === OpCodes.BinaryFrame) {
      length = Platform.NumberUtilities.bytesToString(base64ToSize(frame.text));
      description = opCodeDescriptions[frame.opCode];

    } else {
      dataText = description;
    }

    super({data: description, length: length, time: timeNode});

    this._url = url;
    this._frame = frame;
    this._isTextFrame = isTextFrame;
    this._dataText = dataText;

    /** @type {?BinaryResourceView} */
    this._binaryView = null;
  }

  /**
   * @override
   * @param {!Element} element
   */
  createCells(element) {
    element.classList.toggle(
        'websocket-frame-view-row-error', this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Error);
    element.classList.toggle(
        'websocket-frame-view-row-send', this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Send);
    element.classList.toggle(
        'websocket-frame-view-row-receive', this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Receive);
    super.createCells(element);
  }

  /**
   * @override
   * @return {number}
   */
  nodeSelfHeight() {
    return 21;
  }

  /**
   * @return {string}
   */
  dataText() {
    return this._dataText;
  }

  /**
   * @return {!OpCodes}
   */
  opCode() {
    return /** @type {!OpCodes} */ (this._frame.opCode);
  }

  /**
   * @return {?BinaryResourceView}
   */
  binaryView() {
    if (this._isTextFrame || this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Error) {
      return null;
    }

    if (!this._binaryView) {
      if (this.dataText.length > 0) {
        this._binaryView =
            new BinaryResourceView(this._dataText, /* url */ '', Common.ResourceType.resourceTypes.WebSocket);
      }
    }
    return this._binaryView;
  }
}

/**
 * @param {!ResourceWebSocketFrameNode} a
 * @param {!ResourceWebSocketFrameNode} b
 * @return {number}
 */
export function ResourceWebSocketFrameNodeTimeComparator(a, b) {
  return a._frame.time - b._frame.time;
}

/** @type {!WeakMap<!SDK.NetworkRequest.NetworkRequest, number>} */
const _clearFrameOffsets = new WeakMap();
