// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
export class NetworkWaterfallColumn extends UI.VBox {
  /**
   * @param {!Network.NetworkTimeCalculator} calculator
   */
  constructor(calculator) {
    // TODO(allada) Make this a shadowDOM when the NetworkWaterfallColumn gets moved into NetworkLogViewColumns.
    super(false);
    this.registerRequiredCSS('network/networkWaterfallColumn.css');

    this._canvas = this.contentElement.createChild('canvas');
    this._canvas.tabIndex = -1;
    this.setDefaultFocusedElement(this._canvas);
    this._canvasPosition = this._canvas.getBoundingClientRect();

    /** @const */
    this._leftPadding = 5;
    /** @const */
    this._fontSize = 10;

    this._rightPadding = 0;
    this._scrollTop = 0;

    this._headerHeight = 0;
    this._calculator = calculator;

    // this._rawRowHeight captures model height (41 or 21px),
    // this._rowHeight is computed height of the row in CSS pixels, can be 20.8 for zoomed-in content.
    this._rawRowHeight = 0;
    this._rowHeight = 0;

    this._offsetWidth = 0;
    this._offsetHeight = 0;
    this._startTime = this._calculator.minimumBoundary();
    this._endTime = this._calculator.maximumBoundary();

    this._popoverHelper = new UI.PopoverHelper(this.element, this._getPopoverRequest.bind(this));
    this._popoverHelper.setHasPadding(true);
    this._popoverHelper.setTimeout(300, 300);

    /** @type {!Array<!Network.NetworkNode>} */
    this._nodes = [];

    /** @type {?Network.NetworkNode} */
    this._hoveredNode = null;

    /** @type {!Map<string, !Array<number>>} */
    this._eventDividers = new Map();

    /** @type {(number|undefined)} */
    this._updateRequestID;

    this.element.addEventListener('mousemove', this._onMouseMove.bind(this), true);
    this.element.addEventListener('mouseleave', event => this._setHoveredNode(null, false), true);
    this.element.addEventListener('click', this._onClick.bind(this), true);

    this._styleForTimeRangeName = NetworkWaterfallColumn._buildRequestTimeRangeStyle();

    const resourceStyleTuple = NetworkWaterfallColumn._buildResourceTypeStyle();
    /** @type {!Map<!Common.ResourceType, !NetworkWaterfallColumn._LayerStyle>} */
    this._styleForWaitingResourceType = resourceStyleTuple[0];
    /** @type {!Map<!Common.ResourceType, !NetworkWaterfallColumn._LayerStyle>} */
    this._styleForDownloadingResourceType = resourceStyleTuple[1];

    const baseLineColor = UI.themeSupport.patchColorText('#a5a5a5', UI.ThemeSupport.ColorUsage.Foreground);
    /** @type {!NetworkWaterfallColumn._LayerStyle} */
    this._wiskerStyle = {borderColor: baseLineColor, lineWidth: 1};
    /** @type {!NetworkWaterfallColumn._LayerStyle} */
    this._hoverDetailsStyle = {fillStyle: baseLineColor, lineWidth: 1, borderColor: baseLineColor};

    /** @type {!Map<!NetworkWaterfallColumn._LayerStyle, !Path2D>} */
    this._pathForStyle = new Map();
    /** @type {!Array<!NetworkWaterfallColumn._TextLayer>} */
    this._textLayers = [];

    /** @type {?CSSStyleDeclaration} */
    this._computedDatagridStyle = null;
  }

  /**
   * @return {!Map<!Network.RequestTimeRangeNames, !NetworkWaterfallColumn._LayerStyle>}
   */
  static _buildRequestTimeRangeStyle() {
    const types = Network.RequestTimeRangeNames;
    const styleMap = new Map();
    styleMap.set(types.Connecting, {fillStyle: '#FF9800'});
    styleMap.set(types.SSL, {fillStyle: '#9C27B0'});
    styleMap.set(types.DNS, {fillStyle: '#009688'});
    styleMap.set(types.Proxy, {fillStyle: '#A1887F'});
    styleMap.set(types.Blocking, {fillStyle: '#AAAAAA'});
    styleMap.set(types.Push, {fillStyle: '#8CDBff'});
    styleMap.set(types.Queueing, {fillStyle: 'white', lineWidth: 2, borderColor: 'lightgrey'});
    // This ensures we always show at least 2 px for a request.
    styleMap.set(types.Receiving, {fillStyle: '#03A9F4', lineWidth: 2, borderColor: '#03A9F4'});
    styleMap.set(types.Waiting, {fillStyle: '#00C853'});
    styleMap.set(types.ReceivingPush, {fillStyle: '#03A9F4'});
    styleMap.set(types.ServiceWorker, {fillStyle: 'orange'});
    styleMap.set(types.ServiceWorkerPreparation, {fillStyle: 'orange'});
    return styleMap;
  }

  /**
   * @return {!Array<!Map<!Common.ResourceType, !NetworkWaterfallColumn._LayerStyle>>}
   */
  static _buildResourceTypeStyle() {
    const baseResourceTypeColors = new Map([
      ['document', 'hsl(215, 100%, 80%)'],
      ['font', 'hsl(8, 100%, 80%)'],
      ['media', 'hsl(90, 50%, 80%)'],
      ['image', 'hsl(90, 50%, 80%)'],
      ['script', 'hsl(31, 100%, 80%)'],
      ['stylesheet', 'hsl(272, 64%, 80%)'],
      ['texttrack', 'hsl(8, 100%, 80%)'],
      ['websocket', 'hsl(0, 0%, 95%)'],
      ['xhr', 'hsl(53, 100%, 80%)'],
      ['fetch', 'hsl(53, 100%, 80%)'],
      ['other', 'hsl(0, 0%, 95%)'],
    ]);
    const waitingStyleMap = new Map();
    const downloadingStyleMap = new Map();

    for (const resourceType of Object.values(Common.resourceTypes)) {
      let color = baseResourceTypeColors.get(resourceType.name());
      if (!color) {
        color = baseResourceTypeColors.get('other');
      }
      const borderColor = toBorderColor(color);

      waitingStyleMap.set(resourceType, {fillStyle: toWaitingColor(color), lineWidth: 1, borderColor: borderColor});
      downloadingStyleMap.set(resourceType, {fillStyle: color, lineWidth: 1, borderColor: borderColor});
    }
    return [waitingStyleMap, downloadingStyleMap];

    /**
     * @param {string} color
     */
    function toBorderColor(color) {
      const parsedColor = Common.Color.parse(color);
      const hsla = parsedColor.hsla();
      hsla[1] /= 2;
      hsla[2] -= Math.min(hsla[2], 0.2);
      return parsedColor.asString(null);
    }

    /**
     * @param {string} color
     */
    function toWaitingColor(color) {
      const parsedColor = Common.Color.parse(color);
      const hsla = parsedColor.hsla();
      hsla[2] *= 1.1;
      return parsedColor.asString(null);
    }
  }

  _resetPaths() {
    this._pathForStyle.clear();
    this._pathForStyle.set(this._wiskerStyle, new Path2D());
    this._styleForTimeRangeName.forEach(style => this._pathForStyle.set(style, new Path2D()));
    this._styleForWaitingResourceType.forEach(style => this._pathForStyle.set(style, new Path2D()));
    this._styleForDownloadingResourceType.forEach(style => this._pathForStyle.set(style, new Path2D()));
    this._pathForStyle.set(this._hoverDetailsStyle, new Path2D());
  }

  /**
   * @override
   */
  willHide() {
    this._popoverHelper.hidePopover();
  }

  /**
   * @override
   */
  wasShown() {
    this.update();
  }

  /**
   * @param {!Event} event
   */
  _onMouseMove(event) {
    this._setHoveredNode(this.getNodeFromPoint(event.offsetX, event.offsetY), event.shiftKey);
  }

  /**
   * @param {!Event} event
   */
  _onClick(event) {
    const handled = this._setSelectedNode(this.getNodeFromPoint(event.offsetX, event.offsetY));
    if (handled) {
      event.consume(true);
    }
  }

  /**
   * @param {!Event} event
   * @return {?UI.PopoverRequest}
   */
  _getPopoverRequest(event) {
    if (!this._hoveredNode) {
      return null;
    }
    const request = this._hoveredNode.request();
    if (!request) {
      return null;
    }
    const useTimingBars = !Common.moduleSetting('networkColorCodeResourceTypes').get() && !this._calculator.startAtZero;
    let range;
    let start;
    let end;
    if (useTimingBars) {
      range = Network.RequestTimingView.calculateRequestTimeRanges(request, 0)
                  .find(data => data.name === Network.RequestTimeRangeNames.Total);
      start = this._timeToPosition(range.start);
      end = this._timeToPosition(range.end);
    } else {
      range = this._getSimplifiedBarRange(request, 0);
      start = range.start;
      end = range.end;
    }

    if (end - start < 50) {
      const halfWidth = (end - start) / 2;
      start = start + halfWidth - 25;
      end = end - halfWidth + 25;
    }

    if (event.clientX < this._canvasPosition.left + start || event.clientX > this._canvasPosition.left + end) {
      return null;
    }

    const rowIndex = this._nodes.findIndex(node => node.hovered());
    const barHeight = this._getBarHeight(range.name);
    const y = this._headerHeight + (this._rowHeight * rowIndex - this._scrollTop) + ((this._rowHeight - barHeight) / 2);

    if (event.clientY < this._canvasPosition.top + y || event.clientY > this._canvasPosition.top + y + barHeight) {
      return null;
    }

    const anchorBox = this.element.boxInWindow();
    anchorBox.x += start;
    anchorBox.y += y;
    anchorBox.width = end - start;
    anchorBox.height = barHeight;

    return {
      box: anchorBox,
      show: popover => {
        const content =
            Network.RequestTimingView.createTimingTable(/** @type {!SDK.NetworkRequest} */ (request), this._calculator);
        popover.contentElement.appendChild(content);
        return Promise.resolve(true);
      }
    };
  }

  /**
   * @param {?Network.NetworkNode} node
   * @param {boolean} highlightInitiatorChain
   */
  _setHoveredNode(node, highlightInitiatorChain) {
    if (this._hoveredNode) {
      this._hoveredNode.setHovered(false, false);
    }
    this._hoveredNode = node;
    if (this._hoveredNode) {
      this._hoveredNode.setHovered(true, highlightInitiatorChain);
    }
  }

  /**
   * @param {?Network.NetworkNode} node
   * @returns {boolean}
   */
  _setSelectedNode(node) {
    if (node && node.dataGrid) {
      node.select();
      node.dataGrid.element.focus();
      return true;
    }
    return false;
  }

  /**
   * @param {number} height
   */
  setRowHeight(height) {
    this._rawRowHeight = height;
    this._updateRowHeight();
  }

  _updateRowHeight() {
    this._rowHeight = Math.round(this._rawRowHeight * window.devicePixelRatio) / window.devicePixelRatio;
  }

  /**
   * @param {number} height
   */
  setHeaderHeight(height) {
    this._headerHeight = height;
  }

  /**
   * @param {number} padding
   */
  setRightPadding(padding) {
    this._rightPadding = padding;
    this._calculateCanvasSize();
  }

  /**
   * @param {!Network.NetworkTimeCalculator} calculator
   */
  setCalculator(calculator) {
    this._calculator = calculator;
  }

  /**
   * @param {number} x
   * @param {number} y
   * @return {?Network.NetworkNode}
   */
  getNodeFromPoint(x, y) {
    if (y <= this._headerHeight) {
      return null;
    }
    return this._nodes[Math.floor((this._scrollTop + y - this._headerHeight) / this._rowHeight)];
  }

  scheduleDraw() {
    if (this._updateRequestID) {
      return;
    }
    this._updateRequestID = this.element.window().requestAnimationFrame(() => this.update());
  }

  /**
   * @param {number=} scrollTop
   * @param {!Map<string, !Array<number>>=} eventDividers
   * @param {!Array<!Network.NetworkNode>=} nodes
   */
  update(scrollTop, eventDividers, nodes) {
    if (scrollTop !== undefined && this._scrollTop !== scrollTop) {
      this._popoverHelper.hidePopover();
      this._scrollTop = scrollTop;
    }
    if (nodes) {
      this._nodes = nodes;
      this._calculateCanvasSize();
    }
    if (eventDividers !== undefined) {
      this._eventDividers = eventDividers;
    }
    if (this._updateRequestID) {
      this.element.window().cancelAnimationFrame(this._updateRequestID);
      delete this._updateRequestID;
    }

    this._startTime = this._calculator.minimumBoundary();
    this._endTime = this._calculator.maximumBoundary();
    this._resetCanvas();
    this._resetPaths();
    this._textLayers = [];
    this._draw();
  }

  _resetCanvas() {
    const ratio = window.devicePixelRatio;
    this._canvas.width = this._offsetWidth * ratio;
    this._canvas.height = this._offsetHeight * ratio;
    this._canvas.style.width = this._offsetWidth + 'px';
    this._canvas.style.height = this._offsetHeight + 'px';
  }

  /**
   * @override
   */
  onResize() {
    super.onResize();
    this._updateRowHeight();
    this._calculateCanvasSize();
    this.scheduleDraw();
  }

  _calculateCanvasSize() {
    this._offsetWidth = this.contentElement.offsetWidth - this._rightPadding;
    this._offsetHeight = this.contentElement.offsetHeight;
    this._calculator.setDisplayWidth(this._offsetWidth);
    this._canvasPosition = this._canvas.getBoundingClientRect();
  }

  /**
   * @param {number} time
   * @return {number}
   */
  _timeToPosition(time) {
    const availableWidth = this._offsetWidth - this._leftPadding;
    const timeToPixel = availableWidth / (this._endTime - this._startTime);
    return Math.floor(this._leftPadding + (time - this._startTime) * timeToPixel);
  }

  _didDrawForTest() {
  }

  _draw() {
    const useTimingBars = !Common.moduleSetting('networkColorCodeResourceTypes').get() && !this._calculator.startAtZero;
    const nodes = this._nodes;
    const context = this._canvas.getContext('2d');
    context.save();
    context.scale(window.devicePixelRatio, window.devicePixelRatio);
    context.translate(0, this._headerHeight);
    context.rect(0, 0, this._offsetWidth, this._offsetHeight);
    context.clip();
    const firstRequestIndex = Math.floor(this._scrollTop / this._rowHeight);
    const lastRequestIndex =
        Math.min(nodes.length, firstRequestIndex + Math.ceil(this._offsetHeight / this._rowHeight));
    for (let i = firstRequestIndex; i < lastRequestIndex; i++) {
      const rowOffset = this._rowHeight * i;
      const node = nodes[i];
      this._decorateRow(context, node, rowOffset - this._scrollTop);
      let drawNodes = [];
      if (node.hasChildren() && !node.expanded) {
        drawNodes = /** @type {!Array<!Network.NetworkNode>} */ (node.flatChildren());
      }
      drawNodes.push(node);
      for (const drawNode of drawNodes) {
        if (useTimingBars) {
          this._buildTimingBarLayers(drawNode, rowOffset - this._scrollTop);
        } else {
          this._buildSimplifiedBarLayers(context, drawNode, rowOffset - this._scrollTop);
        }
      }
    }
    this._drawLayers(context);

    context.save();
    context.fillStyle = UI.themeSupport.patchColorText('#888', UI.ThemeSupport.ColorUsage.Foreground);
    for (const textData of this._textLayers) {
      context.fillText(textData.text, textData.x, textData.y);
    }
    context.restore();

    this._drawEventDividers(context);
    context.restore();

    const freeZoneAtLeft = 75;
    const freeZoneAtRight = 18;
    const dividersData = PerfUI.TimelineGrid.calculateGridOffsets(this._calculator);
    PerfUI.TimelineGrid.drawCanvasGrid(context, dividersData);
    PerfUI.TimelineGrid.drawCanvasHeaders(
        context, dividersData, time => this._calculator.formatValue(time, dividersData.precision), this._fontSize,
        this._headerHeight, freeZoneAtLeft);
    context.clearRect(this._offsetWidth - freeZoneAtRight, 0, freeZoneAtRight, this._headerHeight);
    this._didDrawForTest();
  }

  /**
   * @param {!CanvasRenderingContext2D} context
   */
  _drawLayers(context) {
    for (const entry of this._pathForStyle) {
      const style = /** @type {!NetworkWaterfallColumn._LayerStyle} */ (entry[0]);
      const path = /** @type {!Path2D} */ (entry[1]);
      context.save();
      context.beginPath();
      if (style.lineWidth) {
        context.lineWidth = style.lineWidth;
        context.strokeStyle = style.borderColor;
        context.stroke(path);
      }
      if (style.fillStyle) {
        context.fillStyle = style.fillStyle;
        context.fill(path);
      }
      context.restore();
    }
  }

  /**
   * @param {!CanvasRenderingContext2D} context
   */
  _drawEventDividers(context) {
    context.save();
    context.lineWidth = 1;
    for (const color of this._eventDividers.keys()) {
      context.strokeStyle = color;
      for (const time of this._eventDividers.get(color)) {
        context.beginPath();
        const x = this._timeToPosition(time);
        context.moveTo(x, 0);
        context.lineTo(x, this._offsetHeight);
      }
      context.stroke();
    }
    context.restore();
  }

  /**
   * @param {!Network.RequestTimeRangeNames=} type
   * @return {number}
   */
  _getBarHeight(type) {
    const types = Network.RequestTimeRangeNames;
    switch (type) {
      case types.Connecting:
      case types.SSL:
      case types.DNS:
      case types.Proxy:
      case types.Blocking:
      case types.Push:
      case types.Queueing:
        return 7;
      default:
        return 13;
    }
  }

  /**
   * @param {!SDK.NetworkRequest} request
   * @param {number} borderOffset
   * @return {!{start: number, mid: number, end: number}}
   */
  _getSimplifiedBarRange(request, borderOffset) {
    const drawWidth = this._offsetWidth - this._leftPadding;
    const percentages = this._calculator.computeBarGraphPercentages(request);
    return {
      start: this._leftPadding + Math.floor((percentages.start / 100) * drawWidth) + borderOffset,
      mid: this._leftPadding + Math.floor((percentages.middle / 100) * drawWidth) + borderOffset,
      end: this._leftPadding + Math.floor((percentages.end / 100) * drawWidth) + borderOffset
    };
  }

  /**
   * @param {!CanvasRenderingContext2D} context
   * @param {!Network.NetworkNode} node
   * @param {number} y
   */
  _buildSimplifiedBarLayers(context, node, y) {
    const request = node.request();
    if (!request) {
      return;
    }
    const borderWidth = 1;
    const borderOffset = borderWidth % 2 === 0 ? 0 : 0.5;

    const ranges = this._getSimplifiedBarRange(request, borderOffset);
    const height = this._getBarHeight();
    y += Math.floor(this._rowHeight / 2 - height / 2 + borderWidth) - borderWidth / 2;

    const waitingStyle = this._styleForWaitingResourceType.get(request.resourceType());
    const waitingPath = this._pathForStyle.get(waitingStyle);
    waitingPath.rect(ranges.start, y, ranges.mid - ranges.start, height - borderWidth);

    const barWidth = Math.max(2, ranges.end - ranges.mid);
    const downloadingStyle = this._styleForDownloadingResourceType.get(request.resourceType());
    const downloadingPath = this._pathForStyle.get(downloadingStyle);
    downloadingPath.rect(ranges.mid, y, barWidth, height - borderWidth);

    /** @type {?{left: string, right: string, tooltip: (string|undefined)}} */
    let labels = null;
    if (node.hovered()) {
      labels = this._calculator.computeBarGraphLabels(request);
      const barDotLineLength = 10;
      const leftLabelWidth = context.measureText(labels.left).width;
      const rightLabelWidth = context.measureText(labels.right).width;
      const hoverLinePath = this._pathForStyle.get(this._hoverDetailsStyle);

      if (leftLabelWidth < ranges.mid - ranges.start) {
        const midBarX = ranges.start + (ranges.mid - ranges.start - leftLabelWidth) / 2;
        this._textLayers.push({text: labels.left, x: midBarX, y: y + this._fontSize});
      } else if (barDotLineLength + leftLabelWidth + this._leftPadding < ranges.start) {
        this._textLayers.push(
            {text: labels.left, x: ranges.start - leftLabelWidth - barDotLineLength - 1, y: y + this._fontSize});
        hoverLinePath.moveTo(ranges.start - barDotLineLength, y + Math.floor(height / 2));
        hoverLinePath.arc(ranges.start, y + Math.floor(height / 2), 2, 0, 2 * Math.PI);
        hoverLinePath.moveTo(ranges.start - barDotLineLength, y + Math.floor(height / 2));
        hoverLinePath.lineTo(ranges.start, y + Math.floor(height / 2));
      }

      const endX = ranges.mid + barWidth + borderOffset;
      if (rightLabelWidth < endX - ranges.mid) {
        const midBarX = ranges.mid + (endX - ranges.mid - rightLabelWidth) / 2;
        this._textLayers.push({text: labels.right, x: midBarX, y: y + this._fontSize});
      } else if (endX + barDotLineLength + rightLabelWidth < this._offsetWidth - this._leftPadding) {
        this._textLayers.push({text: labels.right, x: endX + barDotLineLength + 1, y: y + this._fontSize});
        hoverLinePath.moveTo(endX, y + Math.floor(height / 2));
        hoverLinePath.arc(endX, y + Math.floor(height / 2), 2, 0, 2 * Math.PI);
        hoverLinePath.moveTo(endX, y + Math.floor(height / 2));
        hoverLinePath.lineTo(endX + barDotLineLength, y + Math.floor(height / 2));
      }
    }

    if (!this._calculator.startAtZero) {
      const queueingRange = Network.RequestTimingView.calculateRequestTimeRanges(request, 0)
                                .find(data => data.name === Network.RequestTimeRangeNames.Total);
      const leftLabelWidth = labels ? context.measureText(labels.left).width : 0;
      const leftTextPlacedInBar = leftLabelWidth < ranges.mid - ranges.start;
      const wiskerTextPadding = 13;
      const textOffset = (labels && !leftTextPlacedInBar) ? leftLabelWidth + wiskerTextPadding : 0;
      const queueingStart = this._timeToPosition(queueingRange.start);
      if (ranges.start - textOffset > queueingStart) {
        const wiskerPath = this._pathForStyle.get(this._wiskerStyle);
        wiskerPath.moveTo(queueingStart, y + Math.floor(height / 2));
        wiskerPath.lineTo(ranges.start - textOffset, y + Math.floor(height / 2));

        // TODO(allada) This needs to be floored.
        const wiskerHeight = height / 2;
        wiskerPath.moveTo(queueingStart + borderOffset, y + wiskerHeight / 2);
        wiskerPath.lineTo(queueingStart + borderOffset, y + height - wiskerHeight / 2 - 1);
      }
    }
  }

  /**
   * @param {!Network.NetworkNode} node
   * @param {number} y
   */
  _buildTimingBarLayers(node, y) {
    const request = node.request();
    if (!request) {
      return;
    }
    const ranges = Network.RequestTimingView.calculateRequestTimeRanges(request, 0);
    for (const range of ranges) {
      if (range.name === Network.RequestTimeRangeNames.Total || range.name === Network.RequestTimeRangeNames.Sending ||
          range.end - range.start === 0) {
        continue;
      }

      const style = this._styleForTimeRangeName.get(range.name);
      const path = this._pathForStyle.get(style);
      const lineWidth = style.lineWidth || 0;
      const height = this._getBarHeight(range.name);
      const middleBarY = y + Math.floor(this._rowHeight / 2 - height / 2) + lineWidth / 2;
      const start = this._timeToPosition(range.start);
      const end = this._timeToPosition(range.end);
      path.rect(start, middleBarY, end - start, height - lineWidth);
    }
  }

  /**
   * @param {!CanvasRenderingContext2D} context
   * @param {!Network.NetworkNode} node
   * @param {number} y
   */
  _decorateRow(context, node, y) {
    if (!this._computedDatagridStyle && node.dataGrid) {
      // Get BackgroundColor for Waterfall from css variable on datagrid
      this._computedDatagridStyle = window.getComputedStyle(node.dataGrid.element);
    }
    if (!this._computedDatagridStyle) {
      context.restore();
      return;
    }
    const nodeBgColor = node.backgroundColor();
    context.save();
    context.beginPath();
    context.fillStyle = this._computedDatagridStyle.getPropertyValue(nodeBgColor);
    context.rect(0, y, this._offsetWidth, this._rowHeight);
    context.fill();
    context.restore();
  }
}

/* Legacy exported object */
self.Network = self.Network || {};

/* Legacy exported object */
Network = Network || {};

/**
 * @constructor
 */
Network.NetworkWaterfallColumn = NetworkWaterfallColumn;

/** @typedef {!{fillStyle: (string|undefined), lineWidth: (number|undefined), borderColor: (string|undefined)}} */
Network.NetworkWaterfallColumn._LayerStyle;

/** @typedef {!{x: number, y: number, text: string}} */
Network.NetworkWaterfallColumn._TextLayer;
