/**
 * @module modules/plot-simple-sk
 * @description <h2><code>plot-simple-sk</code></h2>
 *
 *  A custom element for plotting x,y graphs.
 *
 *  The canvas is broken into two areas, the summary and the details. The
 *  summary is always SUMMARY_HEIGHT pixels high. Also note that we use
 *  window.devicePixelRatio to decide the actual number of pixels to use, and
 *  then use CSS transform to squash the canvas back down to the desired size.
 *
 *    +----------------------------------------------------+
 *    |                                                    |
 *    |                   MARGIN                           |
 *    |                                                    |
 *    |   +--------------------------------------------+   |
 *    |   |           Summary                          |   |
 *    |   |                                            |   |
 *    |   +--------------------------------------------+   |
 *    |                                                    |
 *    |                   MARGIN                           |
 *    |                                                    |
 *    |   +--------------------------------------------+   |
 *    |   |          Details                           |   |
 *    |   |                                            |   |
 *    |   |                                            |   |
 *    |   |                                            |   |
 *    |   |                                            |   |
 *    |   |                                            |   |
 *    |   |                                            |   |
 *    |   |                                            |   |
 *    |   +--------------------------------------------+   |
 *    |                                                    |
 *    |                   MARGIN                           |
 *    |                                                    |
 *    +----------------------------------------------------+
 *
 * To keep rendering quick the traces will be written into Path2D objects to be
 * used for quick rendering.
 *
 * We also use a k-d Tree for quick lookup for clicking and mouse movement over
 * the traces.
 *
 * There are actually two canvas's in play, the trace canvas is below the
 * overlay canvas. The trace canvas contains all the traces in the summary and
 * details along with their axes. The overlay canvas contains everything that
 * changes quickly, such as the crosshairs, the x-bar, etc.
 *
 * This element knows about elements-sk/themes and uses those CSS variables if
 * present.
 *
 * Listens for "theme-chooser-toggle" event on the document and redraws with
 * updated computed style colors.
 *
 * @evt trace_selected - Event produced when the user clicks on a line. The
 *     e.detail contains the id of the line and the index of the point in the
 *     line closest to the mouse, and the [x, y] value of the point in 'pt'.
 *
 *     <pre>
 *     {
 *        x: x,
 *        y: y,
 *        name: name,
 *      }
 *     </pre>
 *
 * @evt trace_focused - Event produced when the user moves the mouse close to a
 *     line. The e.detail contains the id of the line and the index of the point
 *     in the line closest to the mouse.
 *
 *     <pre>
 *     {
 *        x: x,
 *        y: y,
 *        name: name,
 *      }
 *     </pre>
 *
 * @evt zoom - Event produced when the user has zoomed into a region by
 *      dragging. The detail is of the form:
 *
 *      {
 *        xBegin: new Date(),
 *        xEnd: new Date(),
 *      }
 *
 * @attr width - The width of the element in px.
 *
 * @attr height - The height of the element in px.
 *
 * @attr summary {Boolean} - If present then display the summary bar.
 */
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import * as d3Scale from 'd3-scale';
import * as d3Array from 'd3-array';
import * as ResizeObserverPolyfill from 'resize-observer-polyfill';
// This import is needed because https://github.com/Microsoft/TypeScript/issues/28502
import ResizeObserver from 'resize-observer-polyfill';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { KDTree, KDPoint } from './kd';
import { ticks } from './ticks';

//  Prefix for trace ids that are not real traces, such as special_zero. Special
//  traces never receive focus and can't be clicked on.
const SPECIAL = 'special';

export const MISSING_DATA_SENTINEL = 1e32;

const NUM_Y_TICKS = 4;

const HOVER_COLOR = '#8887'; // Note the alpha value.

const ZOOM_RECT_COLOR = '#0007'; // Note the alpha value.

const SUMMARY_LINE_WIDTH = 1; // px

const DETAIL_LINE_WIDTH = 1; // px

const AXIS_LINE_WIDTH = 1; // px

// As backup use a Polyfill for ResizeObserver if it isn't supported. This can
// go away when Safari supports ResizeObserver:
// https://caniuse.com/#feat=resizeobserver
const LocalResizeObserver = ResizeObserver || ResizeObserverPolyfill;

/**
 * @constant {Array} - Colors used for traces.
 */
const COLORS = [
  '#000000',
  '#1B9E77',
  '#D95F02',
  '#7570B3',
  '#E7298A',
  '#66A61E',
  '#E6AB02',
  '#A6761D',
  '#666666',
];

// Contains linear scales to convert from source coordinates into
// device/destination coordinates.
interface Range {
  x: d3Scale.ScaleLinear<number, number>;
  y: d3Scale.ScaleLinear<number, number>;
}

// A trace is drawn as a set of lines overdrawn with dots at each measurement.
interface TracePaths {
  linePath: Path2D | null;
  dotsPath: Path2D | null;
}

/** @class Builds the Path2D objects that describe the trace and the dots for a given
 *   set of scales.
 */
class PathBuilder {
  // TODO(jcgregorio) Change to TracePaths.
  private linePath: Path2D;

  private dotsPath: Path2D;

  // TODO(jcgregorio) Change to Range.
  private xRange: d3Scale.ScaleLinear<number, number>;

  private yRange: d3Scale.ScaleLinear<number, number>;

  private radius: number;

  constructor(
    xRange: d3Scale.ScaleLinear<number, number>,
    yRange: d3Scale.ScaleLinear<number, number>,
    radius: number,
  ) {
    this.xRange = xRange;
    this.yRange = yRange;
    this.radius = radius;
    this.linePath = new Path2D();
    this.dotsPath = new Path2D();
  }

  /**
   * Add a point to plot to the path.
   *
   * @param {Number} x - X coordinate in source coordinates.
   * @param {Number} y - Y coordinate in source coordinates.
   */
  add(x: number, y: number) {
    // Convert source coord into canvas coords.
    const cx = this.xRange(x);
    const cy = this.yRange(y);

    if (x === 0) {
      this.linePath.moveTo(cx, cy);
    } else {
      this.linePath.lineTo(cx, cy);
    }
    this.dotsPath.moveTo(cx + this.radius, cy);
    this.dotsPath.arc(cx, cy, this.radius, 0, 2 * Math.PI);
  }

  /**
   * Returns the Arrays of Path2D objects that represent all the traces.
   *
   * @returns {Object}
   */
  paths(): TracePaths {
    return {
      linePath: this.linePath,
      dotsPath: this.dotsPath,
    };
  }
}

interface Point {
  x: number;
  y: number;
}

interface Rect extends Point {
  width: number;
  height: number;
}

interface SearchPoint extends Point {
  // Source coordinates.
  sx: number;
  sy: number;
  name: string;
}

/**
 * @class Builds a kdTree for searcing for nearest points to the mouse.
 */
class SearchBuilder {
  // TODO(jcgregorio) Change to Range.
  private xRange: d3Scale.ScaleLinear<number, number>;

  private yRange: d3Scale.ScaleLinear<number, number>;

  private points: SearchPoint[];

  constructor(
    xRange: d3Scale.ScaleLinear<number, number>,
    yRange: d3Scale.ScaleLinear<number, number>,
  ) {
    this.xRange = xRange;
    this.yRange = yRange;
    this.points = [];
  }

  /**
   * Add a point to the kdTree.
   *
   * Note that add() stores the x and y coords as 'sx' and 'sy' in the KDTree nodes,
   * and the canvas coords, which are computed from sx and sy are stored as 'x'
   * and 'y' in the KDTree nodes.
   *
   * @param {Number} x - X coordinate in source coordinates.
   * @param {Number} y - Y coordinate in source coordinates.
   * @param {String} name - The trace name.
   */
  add(x: number, y: number, name: string) {
    if (name.startsWith(SPECIAL)) {
      return;
    }

    // Convert source coord into canvas coords.
    const cx = this.xRange(x);
    const cy = this.yRange(y);

    this.points.push({
      x: cx,
      y: cy,
      sx: x,
      sy: y,
      name,
    });
  }

  /**
   * Returns a kdTree that contains all the points being plotted.
   *
   * @returns {KDTree}
   */
  kdTree() {
    const distance = (a: KDPoint, b: KDPoint) => {
      const dx = a.x - b.x;
      const dy = a.y - b.y;
      return dx * dx + dy * dy;
    };

    return new KDTree(this.points, distance, ['x', 'y']);
  }
}

// Returns true if pt is in rect.
function inRect(pt: Point, rect: Rect): boolean {
  return (
    pt.x >= rect.x
    && pt.x < rect.x + rect.width
    && pt.y >= rect.y
    && pt.y < rect.y + rect.height
  );
}

// Restricts pt to rect.
function clampToRect(pt: Point, rect: Rect) {
  if (pt.x < rect.x) {
    pt.x = rect.x;
  } else if (pt.x > rect.x + rect.width) {
    pt.x = rect.x + rect.width;
  }
  if (pt.y < rect.y) {
    pt.y = rect.y;
  } else if (pt.y > rect.y + rect.height) {
    pt.y = rect.y + rect.height;
  }
}

// Clip the given Canvas2D context to the given rect.
function clipToRect(ctx: CanvasRenderingContext2D, rect: Rect) {
  ctx.beginPath();
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
  ctx.clip();
}

// All the data for a single trace.
interface LineData {
  name: string;
  values: number[];
  color: string;
  detail: TracePaths;
  summary: TracePaths;
}

interface MousePosition {
  clientX: number;
  clientY: number;
}

interface MouseMoveRaw extends MousePosition {
  // Is the shift key being pressed as the mouse moves.
  shiftKey: boolean;
}

interface HoverPoint extends Point {
  // The trace id.
  name: string;
}

interface Label extends Point {
  // The text value of the label.
  text: string;
}

interface CrosshairPoint extends Point {
  shift: boolean;
}

// Common information for both the Summary and Detail display areas.
interface Area {
  rect: Rect;
  axis: {
    path: Path2D;
    labels: Label[];
  };
  range: Range;
}

type SummaryArea = Area

interface DetailArea extends Area {
  yaxis: {
    path: Path2D;
    labels: Label[];
  };
}

// Describes the zoom in terms of x-axis source values.
type ZoomRange = [number, number] | null;

// Used for both the trace_selected and trace_focused events.
export interface PlotSimpleSkTraceEventDetails {
  x: number;
  y: number;

  // The trace id.
  name: string;
}

export interface PlotSimpleSkZoomEventDetails {
  xBegin: Date;
  xEnd: Date;
}

export class PlotSimpleSk extends ElementSk {
  // The location of the XBar. See the xbar property..
  private _xbar: number;

  // The locations of the background bands. See bands property.
  private _bands: number[];

  // A map of trace names to 'true' of traces that are highlighted.
  private _highlighted: { [key: string]: boolean };

  // The data we are plotting.
  // An array of objects of this form:
  //   {
  //     name: key,
  //     values: [1.0, 1.1, 0.9, ...],
  //     detail: {
  //       linePath: Path2D,
  //       dotsPath: Path2D,
  //     },
  //     summary: {
  //       linePath: Path2D,
  //       dotsPath: Path2D,
  //     },
  //   }
  private _lineData: LineData[];

  // An array of Date()'s the same length as the values in _lineData.
  private _labels: Date[];

  // The current zoom, either null or an array of two values in source x
  // coordinates, e.g. [1, 12].
  private _zoom: ZoomRange;

  // The source coordinate where a zoom started.
  private _zoomBegin: number;

  // True if we are currently drag zooming, i.e. the mouse is pressed and
  // moving over the summary.
  private _inZoomDrag: boolean;

  // The Canvas 2D context of the traces canvas.
  private _ctx: CanvasRenderingContext2D | null;

  // The Canvas 2D context of the overlay canvas.
  private _overlayCtx: CanvasRenderingContext2D | null;

  // The window.devicePixelRatio.
  private _scale: number;

  // A copy of the clientX, clientY, and shiftKey values of mousemove events,
  // or null if a mousemove event hasn't occurred since the last time it was
  // processed.
  private _mouseMoveRaw: MouseMoveRaw | null;

  // A kdTree for all the points being displayed, in source coordinates. Is
  // null if no traces are being displayed.
  private _pointSearch: KDTree<SearchPoint> | null;

  // The closest trace point to the mouse. May be {} if no traces are
  // displayed or the mouse hasn't moved over the canvas yet. Has the form:
  //   {
  //     x: x,
  //     y: y,
  //     name: String, // name of trace
  //   }
  private _hoverPt: HoverPoint;

  // The location of the crosshair in canvas coordinates. Of the form:
  //   {
  //     x: x,
  //     y: y,
  //     shift: Boolean,
  //   }
  //
  // The value of shift is true of the shift key is being pressed while the
  // mouse moves.
  // }
  private _crosshair: CrosshairPoint;

  // All the info we need about the summary area.
  private _summary: SummaryArea;

  // All the info we need about the details area.
  private _detail: DetailArea;

  // The total number of points we are displaying. Used to decide whether or
  // not to update the details traces when zooming.
  private _numPoints: number;

  // A task to rebuild the k-d search tree used for finding the closest point
  // to the mouse. The actual value is a window.setTimer timerId or zero if no
  // task is scheduled.
  //
  // See https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
  // for details on tasks vs microtasks.
  private _recalcSearchTask: number;

  // A task to do the actual re-draw work of a zoom. The actual value is a
  // window.setTimer timerId or zero if no task is scheduled.
  //
  // See https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
  // for details on tasks vs microtasks.
  private _zoomTask: number;

  // A formatter that prints numbers nicely, such as adding commas. Used when
  // display the hover text.
  private _numberFormatter: Intl.NumberFormat;

  private SUMMARY_HEIGHT!: number; // px

  private SUMMARY_BAR_WIDTH!: number; // px

  private DETAIL_BAR_WIDTH!: number; // px

  private SUMMARY_HIGHLIGHT_LINE_WIDTH!: number; // px

  private DETAIL_RADIUS!: number; // px

  private SUMMARY_RADIUS!: number; // The radius of points in the summary area. (px)

  private MARGIN!: number; // The margin around the details and summary areas. (px)

  private LEFT_MARGIN!: number; // px

  private Y_AXIS_TICK_LENGTH!: number; // px

  private LABEL_FONT_SIZE!: number; // px

  private LABEL_MARGIN!: number; // px

  private LABEL_FONT!: string; // CSS font string.

  private ZOOM_BAR_LINE_WIDTH!: number; // px

  private HOVER_LINE_WIDTH!: number; // px

  private LABEL_COLOR!: string; // CSS color.

  private LABEL_BACKGROUND!: string; // CSS color.

  private CROSSHAIR_COLOR!: string; // CSS color.

  private BAND_COLOR!: string; // CSS color.

  constructor() {
    super(PlotSimpleSk.template);

    // The location of the XBar. See the xbar property..
    this._xbar = -1;

    // The locations of the background bands. See bands property.
    this._bands = [];

    // A map of trace names to 'true' of traces that are highlighted.
    this._highlighted = {};

    // The data we are plotting.
    // An array of objects of this form:
    //   {
    //     name: key,
    //     values: [1.0, 1.1, 0.9, ...],
    //     detail: {
    //       linePath: Path2D,
    //       dotsPath: Path2D,
    //     },
    //     summary: {
    //       linePath: Path2D,
    //       dotsPath: Path2D,
    //     },
    //   }
    this._lineData = [];

    // An array of Date()'s the same length as the values in _lineData.
    this._labels = [];

    // The current zoom, either null or an array of two values in source x
    // coordinates, e.g. [1, 12].
    this._zoom = null;

    // True if we are currently drag zooming, i.e. the mouse is pressed and
    // moving over the summary.
    this._inZoomDrag = false;

    this._zoomBegin = 0;

    // The Canvas 2D context of the traces canvas.
    this._ctx = null;

    // The Canvas 2D context of the overlay canvas.
    this._overlayCtx = null;

    // The window.devicePixelRatio.
    this._scale = 1.0;

    // A copy of the clientX, clientY, and shiftKey values of mousemove events,
    // or null if a mousemove event hasn't occurred since the last time it was
    // processed.
    this._mouseMoveRaw = null;

    // A kdTree for all the points being displayed, in source coordinates. Is
    // null if no traces are being displayed.
    this._pointSearch = null;

    // The closest trace point to the mouse. May be {} if no traces are
    // displayed or the mouse hasn't moved over the canvas yet. Has the form:
    //   {
    //     x: x,
    //     y: y,
    //     name: String, // name of trace
    //   }
    this._hoverPt = {
      x: -1,
      y: -1,
      name: '',
    };

    // The location of the crosshair in canvas coordinates. Of the form:
    //   {
    //     x: x,
    //     y: y,
    //     shift: Boolean,
    //   }
    //
    // The value of shift is true of the shift key is being pressed while the
    // mouse moves.
    // }
    this._crosshair = {
      x: -1,
      y: -1,
      shift: false,
    };

    // All the info we need about the summary area.
    this._summary = {
      rect: {
        x: 0,
        y: 0,
        width: 0,
        height: 0,
      },
      axis: {
        path: new Path2D(), // Path2D.
        labels: [], // The labels and locations to draw them. {x, y, text}.
      },
      range: {
        x: d3Scale.scaleLinear(),
        y: d3Scale.scaleLinear(),
      },
    };

    // All the info we need about the details area.
    this._detail = {
      rect: {
        x: 0,
        y: 0,
        width: 0,
        height: 0,
      },
      axis: {
        path: new Path2D(), // Path2D.
        labels: [], // The labels and locations to draw them. {x, y, text}.
      },
      yaxis: {
        path: new Path2D(),
        labels: [], // The labels and locations to draw them. {x, y, text}.
      },
      range: {
        x: d3Scale.scaleLinear(),
        y: d3Scale.scaleLinear(),
      },
    };

    // The total number of points we are displaying. Used to decide whether or
    // not to update the details traces when zooming.
    this._numPoints = 0;

    // A task to rebuild the k-d search tree used for finding the closest point
    // to the mouse. The actual value is a window.setTimer timerId or zero if no
    // task is scheduled.
    //
    // See https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
    // for details on tasks vs microtasks.
    this._recalcSearchTask = 0;

    // A task to do the actual re-draw work of a zoom. The actual value is a
    // window.setTimer timerId or zero if no task is scheduled.
    //
    // See https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
    // for details on tasks vs microtasks.
    this._zoomTask = 0;

    // A formatter that prints numbers nicely, such as adding commas. Used when
    // display the hover text.
    this._numberFormatter = new Intl.NumberFormat();

    this._upgradeProperty('width');
    this._upgradeProperty('height');
    this._upgradeProperty('bands');
    this._upgradeProperty('xbar');
    this._upgradeProperty('hightlight');
    this._upgradeProperty('zoom');

    this._updateScaledMeasurements();
  }


  // Note that in both of the canvas elements we are setting a CSS transform that
  // takes into account window.devicePixelRatio, that is, we are drawing to a
  // scale that matches the displays native resolution and then scaling that back
  // to fit on the page. Also see _updateScaledMeasurements for how the device
  // pixel ratio affects all of our pixel calculations.
  private static template = (ele: PlotSimpleSk) => html`
    <canvas
      class="traces"
      width=${ele.width * window.devicePixelRatio}
      height=${ele.height * window.devicePixelRatio}
      style="transform-origin: 0 0; transform: scale(${1
      / window.devicePixelRatio});"
    ></canvas>
    <canvas
      class="overlay"
      width=${ele.width * window.devicePixelRatio}
      height=${ele.height * window.devicePixelRatio}
      style="transform-origin: 0 0; transform: scale(${1
      / window.devicePixelRatio});"
    ></canvas>
  `;


  connectedCallback(): void {
    super.connectedCallback();

    this.render();

    // We need to dynamically resize the canvas elements since they don't do
    // that themselves.
    const resizeObserver = new LocalResizeObserver((entries) => {
      entries.forEach((entry) => {
        this.width = entry.contentRect.width;
      });
    });
    resizeObserver.observe(this);

    this.addEventListener('mousemove', (e) => {
      // Do as little as possible here. The _raf() function will periodically
      // check if the mouse has moved and trigger the appropriate redraws.
      this._mouseMoveRaw = {
        clientX: e.clientX,
        clientY: e.clientY,
        shiftKey: e.shiftKey,
      };
    });

    this.addEventListener('mousedown', (e) => {
      const pt = this._eventToCanvasPt(e);
      // If you click in the summary area then begin zooming via drag.
      if (inRect(pt, this._summary.rect!)) {
        const zx = this._summary.range.x.invert(pt.x);
        this._inZoomDrag = true;
        this._zoomBegin = zx;
        this.zoom = [zx, zx + 0.01]; // Add a smidge to the second zx to avoid a degenerate detail plot.
      }
    });

    this.addEventListener('mouseup', () => {
      if (this._inZoomDrag) {
        this._dispatchZoomEvent();
      }
      this._inZoomDrag = false;
    });

    this.addEventListener('mouseleave', () => {
      if (this._inZoomDrag) {
        this._dispatchZoomEvent();
      }
      this._inZoomDrag = false;
    });

    this.addEventListener('click', (e) => {
      const pt = this._eventToCanvasPt(e);
      if (!inRect(pt, this._detail.rect)) {
        return;
      }
      if (!this._pointSearch) {
        return;
      }
      const closest = this._pointSearch.nearest(pt);
      const detail = {
        x: closest.sx,
        y: closest.sy,
        name: closest.name,
      };
      this.dispatchEvent(
        new CustomEvent<PlotSimpleSkTraceEventDetails>('trace_selected', {
          detail,
          bubbles: true,
        }),
      );
    });

    // If the user toggles the theme to/from darkmode then redraw.
    document.addEventListener('theme-chooser-toggle', () => {
      this.render();
    });

    window.requestAnimationFrame(this._raf.bind(this));
  }

  attributeChangedCallback(_: string, oldValue: string, newValue: string): void {
    if (oldValue !== newValue) {
      this.render();
    }
  }

  // Call this when the width or height attrs have changed.
  render(): void {
    this._render();
    const canvas = this.querySelector<HTMLCanvasElement>('canvas.traces')!;
    const overlayCanvas = this.querySelector<HTMLCanvasElement>(
      'canvas.overlay',
    )!;
    if (canvas) {
      this._ctx = canvas.getContext('2d');
      this._overlayCtx = overlayCanvas.getContext('2d');
      this._scale = window.devicePixelRatio;
      this._updateScaledMeasurements();
      this._updateScaleRanges();
      this._recalcDetailPaths();
      this._recalcSummaryPaths();
      this._drawTracesCanvas();
    }
  }

  /**
   * Adds lines to be displayed.
   *
   * Any line id that begins with 'special' will be treated specially,
   * i.e. it will be presented as a dashed black line that doesn't
   * generate events. This may be useful for adding a line at y=0,
   * or a reference trace.
   *
   * @param {Object} lines - A map from trace id to arrays of y values.
   * @param {Array} labels - An array of Date objects the same length as the values.
   *
   */
  addLines(lines: { [key: string]: number[] | null }, labels: Date[]): void {
    const keys = Object.keys(lines);
    if (keys.length === 0) {
      return;
    }
    const startedEmpty = this._zoom === null && this._lineData.length === 0;
    if (labels) {
      this._labels = labels;
    }

    // Convert into the format we will eventually expect.
    keys.forEach((key) => {
      // You can't encode NaN in JSON, so convert sentinel values to NaN here so
      // that dsArray functions will operate correctly.
      lines[key]!.forEach((x, i) => {
        if (x === MISSING_DATA_SENTINEL) {
          lines[key]![i] = NaN;
        }
      });
      const values = lines[key]!;
      this._lineData.push({
        name: key,
        values,
        color: 'black',
        detail: {
          linePath: null,
          dotsPath: null,
        },
        summary: {
          linePath: null,
          dotsPath: null,
        },
      });
    });

    // Set the zoom if we just added data for the first time.
    if (startedEmpty && this._lineData.length > 0) {
      this._zoom = [0, this._lineData[0].values.length - 1];
    }

    this._updateCount();
    this._updateScaleDomains();
    this._recalcSummaryPaths();
    this._recalcDetailPaths();
    this._drawTracesCanvas();
  }

  /**
   * Delete all the lines whose ids are in 'ids' from being plotted.
   *
   * @param {Array<string>} ids - The trace ids to remove.
   */
  deleteLines(ids: string[]): void {
    this._lineData = this._lineData.filter(
      (line) => ids.indexOf(line.name) === -1,
    );

    const onlySpecialLinesRemaining = this._lineData.every((line) => line.name.startsWith(SPECIAL));
    if (onlySpecialLinesRemaining) {
      this.removeAll();
    } else {
      this._updateCount();
      this._updateScaleDomains();
      this._recalcSummaryPaths();
      this._recalcDetailPaths();
      this._drawTracesCanvas();
    }
  }

  /**
   * Remove all lines from plot.
   */
  removeAll(): void{
    this._lineData = [];
    this._labels = [];
    this._hoverPt = {
      x: -1,
      y: -1,
      name: '',
    };
    this._pointSearch = null;
    this._crosshair = {
      x: -1,
      y: -1,
      shift: false,
    };
    this._mouseMoveRaw = null;
    this._highlighted = {};
    this._xbar = -1;
    this._zoom = null;
    this._inZoomDrag = false;
    this._numPoints = 0;
    this._drawTracesCanvas();
  }


  /**
   * Update all the things that look like constants, but are really dependent on
   * window.devicePixelRatio or the current CSS styling.
   */
  private _updateScaledMeasurements() {
    // The height of the summary area.
    if (this.summary) {
      this.SUMMARY_HEIGHT = 50 * this._scale; // px
    } else {
      this.SUMMARY_HEIGHT = 0;
    }

    this.SUMMARY_BAR_WIDTH = 2 * this._scale; // px

    this.DETAIL_BAR_WIDTH = 3 * this._scale; // px

    this.SUMMARY_HIGHLIGHT_LINE_WIDTH = 3 * this._scale;

    // The radius of points in the details area.
    this.DETAIL_RADIUS = 3 * this._scale; // px

    // The radius of points in the summary area.
    this.SUMMARY_RADIUS = 2 * this._scale; // px

    // The margin around the details and summary areas.
    this.MARGIN = 32 * this._scale; // px

    this.LEFT_MARGIN = 2 * this.MARGIN; // px

    this.Y_AXIS_TICK_LENGTH = this.MARGIN / 4; // px

    this.LABEL_FONT_SIZE = 14 * this._scale; // px

    this.LABEL_MARGIN = 6 * this._scale; // px

    this.LABEL_FONT = `${this.LABEL_FONT_SIZE}px Roboto,Helvetica,Arial,Bitstream Vera Sans,sans-serif`;

    this.ZOOM_BAR_LINE_WIDTH = 3 * this._scale; // px

    this.HOVER_LINE_WIDTH = 1 * this._scale; // px

    this.CROSSHAIR_COLOR = '#f00';

    this.BAND_COLOR = '#888';

    // Pull out the computed colors.
    const style = getComputedStyle(this);

    // Start by using the computed colors.
    this.LABEL_COLOR = style.color;
    this.LABEL_BACKGROUND = style.backgroundColor;

    // Now override with CSS variables if they are present.
    const onBackground = style.getPropertyValue('--on-backgroud');
    if (onBackground !== '') {
      this.LABEL_COLOR = onBackground;
    }

    const background = style.getPropertyValue('--backgroud');
    if (background !== '') {
      this.LABEL_BACKGROUND = background;
    }

    const errorColor = style.getPropertyValue('--error');
    if (errorColor !== '') {
      this.CROSSHAIR_COLOR = errorColor;
    }

    const secondaryColor = style.getPropertyValue('--secondary');
    if (secondaryColor !== '') {
      this.BAND_COLOR = secondaryColor;
    }
  }

  private _dispatchZoomEvent() {
    if (!this._zoom) {
      return;
    }
    let beginIndex = Math.floor(this._zoom[0] - 0.1);
    if (beginIndex < 0) {
      beginIndex = 0;
    }
    let endIndex = Math.ceil(this._zoom[1] + 0.1);
    if (endIndex > this._labels.length - 1) {
      endIndex = this._labels.length - 1;
    }
    const detail = {
      xBegin: this._labels[beginIndex],
      xEnd: this._labels[endIndex],
    };
    this.dispatchEvent(
      new CustomEvent<PlotSimpleSkZoomEventDetails>('zoom', {
        detail,
        bubbles: true,
      }),
    );
  }

  /**
   * Convert mouse event coordinates to a canvas point.
   *
   * @param {Object} e - A mouse event or an object that has the coords stored
   * in clientX and clientY.
   */
  private _eventToCanvasPt(e: MouseMoveRaw) {
    const clientRect = this._ctx!.canvas.getBoundingClientRect();
    return {
      x: (e.clientX - clientRect.left) * this._scale,
      y: (e.clientY - clientRect.top) * this._scale,
    };
  }

  // Handles requestAnimationFrame callbacks.
  private _raf() {
    // Always queue up our next raf first.
    window.requestAnimationFrame(() => this._raf());

    // Bail out early if the mouse hasn't moved.
    if (this._mouseMoveRaw === null) {
      return;
    }
    if (this._inZoomDrag === false) {
      const pt = this._eventToCanvasPt(this._mouseMoveRaw);

      // Update _hoverPt if needed.
      if (this._pointSearch) {
        const closest = this._pointSearch.nearest(pt);
        const detail = {
          x: closest.sx,
          y: closest.sy,
          name: closest.name,
        };
        if (detail.x !== this._hoverPt.x || detail.y !== this._hoverPt.y) {
          this._hoverPt = detail;
          this.dispatchEvent(
            new CustomEvent<PlotSimpleSkTraceEventDetails>('trace_focused', {
              detail,
              bubbles: true,
            }),
          );
        }
      }

      // Update crosshair.
      if (this._mouseMoveRaw.shiftKey && this._pointSearch) {
        this._crosshair = {
          x: pt.x,
          y: pt.y,
          shift: false,
        };
        clampToRect(this._crosshair, this._detail.rect);
      } else {
        this._crosshair = {
          x: this._detail.range.x(this._hoverPt.x),
          y: this._detail.range.y(this._hoverPt.y),
          shift: true,
        };
      }
      this._drawOverlayCanvas();
      this._mouseMoveRaw = null;
    } else {
      // We are zooming.
      const pt = this._eventToCanvasPt(this._mouseMoveRaw);
      clampToRect(pt, this._summary.rect);

      // x in source coordinates.
      const sx = this._summary.range.x.invert(pt.x);

      // Set zoom, always making sure we go from lowest to highest.
      let zoom: ZoomRange = [this._zoomBegin, sx];
      if (this._zoomBegin > sx) {
        zoom = [sx, this._zoomBegin];
      }
      this.zoom = zoom;
    }
  }


  /**
   * This is a super simple hash (h = h * 31 + x_i) currently used
   * for things like assigning colors to graphs based on trace ids. It
   * shouldn't be used for anything more serious than that.
   *
   * @param {String} s - A string to hash.
   * @return {Number} A 32 bit hash for the given string.
   */
  private _hashString(s: string) {
    let hash = 0;
    for (let i = s.length - 1; i >= 0; i--) {
      // eslint-disable-next-line no-bitwise
      hash = (hash << 5) - hash + s.charCodeAt(i);
      // eslint-disable-next-line no-bitwise
      hash |= 0;
    }
    return Math.abs(hash);
  }


  private _updateCount() {
    this._numPoints = 0;
    if (this._lineData.length > 0) {
      this._numPoints = this._lineData.length * this._lineData[0].values.length;
    }
  }

  // Rebuilds our cache of Path2D objects we use for quick rendering.
  private _recalcSummaryPaths() {
    this._lineData.forEach((line) => {
      // Need to pass in the x and y ranges, and the dot radius.
      if (line.name.startsWith(SPECIAL)) {
        line.color = this.LABEL_COLOR;
      } else {
        line.color = COLORS[(this._hashString(line.name) % 8) + 1];
      }

      const summaryBuilder = new PathBuilder(
        this._summary.range.x,
        this._summary.range.y,
        this.SUMMARY_RADIUS,
      );

      line.values.forEach((y, x) => {
        if (Number.isNaN(y)) {
          return;
        }
        summaryBuilder.add(x, y);
      });
      line.summary = summaryBuilder.paths();
    });

    // Build summary x-axis.
    this._recalcXAxis(this._summary, this._labels, 0);
  }

  // Rebuilds our cache of Path2D objects we use for quick rendering.
  private _recalcDetailPaths() {
    const domain = this._detail.range.x.domain();
    domain[0] = Math.floor(domain[0] - 0.1);
    domain[1] = Math.ceil(domain[1] + 0.1);
    this._lineData.forEach((line) => {
      // Need to pass in the x and y ranges, and the dot radius.
      if (line.name.startsWith(SPECIAL)) {
        line.color = this.LABEL_COLOR;
      } else {
        line.color = COLORS[(this._hashString(line.name) % 8) + 1];
      }

      const detailBuilder = new PathBuilder(
        this._detail.range.x,
        this._detail.range.y,
        this.DETAIL_RADIUS,
      );

      line.values.forEach((y, x) => {
        if (Number.isNaN(y)) {
          return;
        }
        if (x < domain[0] || x > domain[1]) {
          return;
        }
        detailBuilder.add(x, y);
      });
      line.detail = detailBuilder.paths();
    });

    // Build detail x-axis.
    const detailDomain = this._detail.range.x.domain();
    const labelOffset = Math.ceil(detailDomain[0]);
    const detailLabels = this._labels.slice(
      Math.ceil(detailDomain[0]),
      Math.floor(detailDomain[1] + 1),
    );
    this._recalcXAxis(this._detail, detailLabels, labelOffset);

    // Build detail y-axis.
    this._recalcYAxis(this._detail);
    this._recalcSearch();
  }

  // Recalculates the y-axis info.
  private _recalcYAxis(area: DetailArea) {
    const yAxisPath = new Path2D();
    const thinX = Math.floor(this._detail.rect.x) + 0.5; // Make sure we get a thin line. https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors#A_lineWidth_example
    yAxisPath.moveTo(thinX, this._detail.rect.y);
    yAxisPath.lineTo(thinX, this._detail.rect.y + this._detail.rect.height);
    area.yaxis.labels = [];
    area.range.y.ticks(NUM_Y_TICKS).forEach((t) => {
      const label = {
        x: 0,
        y: Math.floor(area.range.y(t)) + 0.5,
        text: `${this._numberFormatter.format(t)}`,
      };
      area.yaxis.labels.push(label);
      yAxisPath.moveTo(thinX, label.y);
      yAxisPath.lineTo(thinX - this.Y_AXIS_TICK_LENGTH, label.y);
    });
    area.yaxis.path = yAxisPath;
  }

  // Recalculates the x-axis info.
  private _recalcXAxis(area: Area, labels: Date[], labelOffset: number) {
    const xAxisPath = new Path2D();
    const thinY = Math.floor(area.rect.y) + 0.5; // Make sure we get a thin line.
    xAxisPath.moveTo(area.rect.x + 0.5, thinY);
    xAxisPath.lineTo(area.rect.x + 0.5 + area.rect.width, thinY);
    area.axis.labels = [];
    ticks(labels).forEach((tick) => {
      const label = {
        x: Math.floor(area.range.x(tick.x + labelOffset)) + 0.5,
        y: area.rect.y - this.MARGIN / 2,
        text: tick.text,
      };
      area.axis.labels.push(label);
      xAxisPath.moveTo(label.x, area.rect.y);
      xAxisPath.lineTo(label.x, area.rect.y - this.MARGIN / 2);
    });
    area.axis.path = xAxisPath;
  }

  // Rebuilds the kdTree we use to look up closest points.
  private _recalcSearch() {
    if (this._recalcSearchTask) {
      return;
    }
    this._recalcSearchTask = window.setTimeout(() => this._recalcSearchImpl());
  }

  private _recalcSearchImpl() {
    if (this._zoomTask) {
      // If there is a pending zoom task then let that complete first since zooming
      // invalidates the search tree and it needs to be built again.
      this._recalcSearchTask = window.setTimeout(() => this._recalcSearchImpl());
      return;
    }
    const domain = this._detail.range.x.domain();
    domain[0] = Math.floor(domain[0] - 0.1);
    domain[1] = Math.ceil(domain[1] + 0.1);
    const searchBuilder = new SearchBuilder(
      this._detail.range.x,
      this._detail.range.y,
    );
    this._lineData.forEach((line) => {
      line.values.forEach((y, x) => {
        if (Number.isNaN(y)) {
          return;
        }
        if (x < domain[0] || x > domain[1]) {
          return;
        }
        searchBuilder.add(x, y, line.name);
      });
    });
    this._pointSearch = searchBuilder.kdTree();
    this._recalcSearchTask = 0;
  }

  // Updates all of our d3Scale domains.
  private _updateScaleDomains() {
    let domainEnd = 1;
    if (this._lineData && this._lineData.length) {
      domainEnd = this._lineData[0].values.length - 1;
    }
    if (this._zoom) {
      this._detail.range.x = this._detail.range.x.domain(this._zoom);
    } else {
      this._detail.range.x = this._detail.range.x.domain([0, domainEnd]);
    }

    this._summary.range.x = this._summary.range.x.domain([0, domainEnd]);

    const domain = [
      d3Array.min(this._lineData, (line) => d3Array.min(line.values))!,
      d3Array.max(this._lineData, (line) => d3Array.max(line.values))!,
    ];

    this._detail.range.y = this._detail.range.y.domain(domain).nice();

    this._summary.range.y = this._summary.range.y.domain(domain);
  }

  // Updates all of our d3Scale ranges. Also updates detail and summary rects.
  private _updateScaleRanges() {
    const width = this._ctx!.canvas.width;
    const height = this._ctx!.canvas.height;

    this._summary.range.x = this._summary.range.x.range([
      this.LEFT_MARGIN,
      width - this.MARGIN,
    ]);

    this._summary.range.y = this._summary.range.y.range([
      this.SUMMARY_HEIGHT + this.MARGIN,
      this.MARGIN,
    ]);

    this._detail.range.x = this._detail.range.x.range([
      this.LEFT_MARGIN,
      width - this.MARGIN,
    ]);

    this._detail.range.y = this._detail.range.y.range([
      height - this.MARGIN,
      this.SUMMARY_HEIGHT + 2 * this.MARGIN,
    ]);

    this._summary.rect = {
      x: this.LEFT_MARGIN,
      y: this.MARGIN,
      width: width - this.MARGIN - this.LEFT_MARGIN,
      height: this.SUMMARY_HEIGHT,
    };

    this._detail.rect = {
      x: this.LEFT_MARGIN,
      y: this.SUMMARY_HEIGHT + 2 * this.MARGIN,
      width: width - this.MARGIN - this.LEFT_MARGIN,
      height: height - this.SUMMARY_HEIGHT - 3 * this.MARGIN,
    };
  }

  // Draw the contents of the overlay canvas.
  private _drawOverlayCanvas() {
    // Always start by clearing the overlay.
    const width = this._overlayCtx!.canvas.width;
    const height = this._overlayCtx!.canvas.height;
    const ctx = this._overlayCtx!;

    ctx.clearRect(0, 0, width, height);

    if (this.summary) {
      // First clip to the summary region.
      ctx.save();
      {
        // Block to scope save/restore.
        clipToRect(ctx, this._summary.rect);

        // Draw the xbar.
        this._drawXBar(ctx, this._summary, this.SUMMARY_BAR_WIDTH);

        // Draw the bands.
        this._drawBands(ctx, this._summary, this.SUMMARY_BAR_WIDTH);

        // Draw the zoom on the summary.
        if (this._zoom !== null) {
          ctx.lineWidth = this.ZOOM_BAR_LINE_WIDTH;
          ctx.strokeStyle = this.LABEL_COLOR;

          // Draw left bar.
          const leftx = this._summary.range.x(this._zoom[0]);
          ctx.beginPath();
          ctx.moveTo(leftx, this._summary.rect.y);
          ctx.lineTo(leftx, this._summary.rect.y + this._summary.rect.height);

          // Draw right bar.
          const rightx = this._summary.range.x(this._zoom[1]);
          ctx.moveTo(rightx, this._summary.rect.y);
          ctx.lineTo(rightx, this._summary.rect.y + this._summary.rect.height);
          ctx.stroke();

          // Draw gray boxes.
          ctx.fillStyle = ZOOM_RECT_COLOR;
          ctx.rect(
            this._summary.rect.x,
            this._summary.rect.y,
            leftx - this._summary.rect.x,
            this._summary.rect.height,
          );
          ctx.rect(
            rightx,
            this._summary.rect.y,
            this._summary.rect.x + this._summary.rect.width - rightx,
            this._summary.rect.height,
          );

          ctx.fill();
        }
      }
      ctx.restore();
    }

    // Now clip to the detail region.
    ctx.save();
    {
      // Block to scope save/restore.
      clipToRect(ctx, this._detail.rect);

      // Draw the xbar.
      this._drawXBar(ctx, this._detail, this.DETAIL_BAR_WIDTH);

      // Draw the bands.
      this._drawBands(ctx, this._detail, this.DETAIL_BAR_WIDTH);

      // Draw highlighted lines.
      this._lineData.forEach((highlightedLine) => {
        if (!(highlightedLine.name in this._highlighted)) {
          return;
        }
        ctx.strokeStyle = highlightedLine.color;
        ctx.fillStyle = this.LABEL_BACKGROUND;
        ctx.lineWidth = this.SUMMARY_HIGHLIGHT_LINE_WIDTH;

        ctx.stroke(highlightedLine.detail.linePath!);
        ctx.fill(highlightedLine.detail.dotsPath!);
        ctx.stroke(highlightedLine.detail.dotsPath!);
      });

      // Find the line currently hovered over.
      let line = null;
      for (let i = 0; i < this._lineData.length; i++) {
        if (this._lineData[i].name === this._hoverPt.name) {
          line = this._lineData[i];
          break;
        }
      }
      if (line !== null) {
        // Draw the hovered line and dots in a different color.
        ctx.strokeStyle = HOVER_COLOR;
        ctx.fillStyle = HOVER_COLOR;
        ctx.lineWidth = this.HOVER_LINE_WIDTH;

        // Just draw the dots, not the line.
        ctx.fill(line.detail.dotsPath!);
        ctx.stroke(line.detail.dotsPath!);
      }

      if (!this._inZoomDrag) {
        // Draw the crosshairs.
        ctx.strokeStyle = this.CROSSHAIR_COLOR;
        ctx.lineWidth = AXIS_LINE_WIDTH;
        ctx.beginPath();
        const thinX = Math.floor(this._crosshair.x) + 0.5; // Make sure we get a thin line.
        const thinY = Math.floor(this._crosshair.y) + 0.5; // Make sure we get a thin line.
        ctx.moveTo(this._detail.rect.x, thinY);
        ctx.lineTo(this._detail.rect.x + this._detail.rect.width, thinY);
        ctx.moveTo(thinX, this._detail.rect.y);
        ctx.lineTo(thinX, this._detail.rect.y + this._detail.rect.height);
        ctx.stroke();

        // Y label at crosshair if shift is pressed.
        if (this._crosshair.shift) {
          // Draw the label offset from the crosshair.
          ctx.font = this.LABEL_FONT;
          ctx.textBaseline = 'bottom';
          const label = this._numberFormatter.format(this._hoverPt.y);
          let x = this._crosshair.x + this.MARGIN;
          let y = this._crosshair.y - this.MARGIN;

          // First draw a white backdrop.
          ctx.fillStyle = this.LABEL_BACKGROUND;
          const meas = ctx.measureText(label);
          const labelHeight = this.LABEL_FONT_SIZE + 2 * this.LABEL_MARGIN;
          const labelWidth = meas.width + this.LABEL_MARGIN * 2;

          // Bump the text to different quadrants so it is always visible.
          if (y < this._detail.rect.y + this._detail.rect.height / 2) {
            y = this._crosshair.y + this.MARGIN;
          }
          if (x > this._detail.rect.x + this._detail.rect.width / 2) {
            x = x - labelWidth - 2 * this.MARGIN;
          }

          ctx.beginPath();
          ctx.rect(
            x - this.LABEL_MARGIN,
            y + this.LABEL_MARGIN,
            labelWidth,
            -labelHeight,
          );
          ctx.fill();
          ctx.strokeStyle = this.LABEL_COLOR;
          ctx.beginPath();
          ctx.rect(
            x - this.LABEL_MARGIN,
            y + this.LABEL_MARGIN,
            labelWidth,
            -labelHeight,
          );
          ctx.stroke();

          // Now draw text on top.
          ctx.fillStyle = this.LABEL_COLOR;
          ctx.fillText(label, x, y);
        }
      }
    }
    ctx.restore();
  }

  // Draw the xbar in the given area with the given width.
  private _drawXBar(ctx: CanvasRenderingContext2D, area: Area, width: number) {
    if (this.xbar === -1) {
      return;
    }
    ctx.lineWidth = width;
    ctx.strokeStyle = this.CROSSHAIR_COLOR;
    const bx = area.range.x(this._xbar);
    ctx.beginPath();
    ctx.moveTo(bx, area.rect.y);
    ctx.lineTo(bx, area.rect.y + area.rect.height);
    ctx.stroke();
  }

  // Draw the bands in the given area with the given width.
  private _drawBands(ctx: CanvasRenderingContext2D, area: Area, width: number) {
    ctx.lineWidth = width;
    ctx.strokeStyle = this.BAND_COLOR;
    ctx.setLineDash([width, width]);
    ctx.beginPath();
    this._bands.forEach((band) => {
      const bx = area.range.x(band);
      ctx.moveTo(bx, area.rect.y);
      ctx.lineTo(bx, area.rect.y + area.rect.height);
    });
    ctx.stroke();
    ctx.setLineDash([]);
  }

  // Draw everything on the trace canvas.
  //
  // Well, not quite everything, if we are drag zooming then we only redraw the
  // details and not the summary.
  private _drawTracesCanvas() {
    const width = this._ctx!.canvas.width;
    const height = this._ctx!.canvas.height;
    const ctx = this._ctx!;

    if (this._inZoomDrag) {
      ctx.clearRect(
        this._detail.rect.x - this.MARGIN,
        this._detail.rect.y - this.MARGIN,
        this._detail.rect.width + 2 * this.MARGIN,
        this._detail.rect.height + 2 * this.MARGIN,
      );
    } else {
      ctx.clearRect(0, 0, width, height);
    }
    ctx.fillStyle = this.LABEL_BACKGROUND;

    // Draw the detail.
    ctx.save();
    {
      // Block to scope save/restore.
      clipToRect(ctx, this._detail.rect);
      this._drawXAxis(ctx, this._detail);
      ctx.fillStyle = this.LABEL_BACKGROUND;

      this._lineData.forEach((line) => {
        ctx.strokeStyle = line.color;
        ctx.lineWidth = DETAIL_LINE_WIDTH;
        ctx.stroke(line.detail.linePath!);
        ctx.fill(line.detail.dotsPath!);
        ctx.stroke(line.detail.dotsPath!);
      });
    }
    ctx.restore();
    this._drawXAxis(ctx, this._detail);

    if (!this._inZoomDrag && this.summary) {
      // Draw the summary.
      ctx.save();
      {
        // Block to scope save/restore.
        clipToRect(ctx, this._summary.rect);
        this._lineData.forEach((line) => {
          ctx.fillStyle = this.LABEL_BACKGROUND;
          ctx.strokeStyle = line.color;
          ctx.lineWidth = SUMMARY_LINE_WIDTH;
          ctx.stroke(line.summary.linePath!);
          ctx.fill(line.summary.dotsPath!);
          ctx.stroke(line.summary.dotsPath!);
        });
      }
      ctx.restore();
      this._drawXAxis(ctx, this._summary);
    }
    // Draw y-Axes.
    this._drawYAxis(ctx, this._detail);

    this._drawOverlayCanvas();
  }

  // Draw a y-axis using the given context in the given area.
  private _drawYAxis(ctx: CanvasRenderingContext2D, area: DetailArea) {
    ctx.strokeStyle = this.LABEL_COLOR;
    ctx.fillStyle = this.LABEL_COLOR;
    ctx.font = this.LABEL_FONT;
    ctx.textBaseline = 'middle';
    ctx.lineWidth = AXIS_LINE_WIDTH;
    ctx.textAlign = 'right';
    ctx.stroke(area.yaxis.path);
    const labelWidth = (3 * this.LEFT_MARGIN) / 4;
    area.yaxis.labels.forEach((label) => {
      ctx.fillText(label.text, label.x + labelWidth, label.y, labelWidth);
    });
  }

  // Draw a x-axis using the given context in the given area.
  private _drawXAxis(ctx: CanvasRenderingContext2D, area: Area) {
    ctx.strokeStyle = this.LABEL_COLOR;
    ctx.fillStyle = this.LABEL_COLOR;
    ctx.font = this.LABEL_FONT;
    ctx.textBaseline = 'middle';
    ctx.lineWidth = AXIS_LINE_WIDTH;
    ctx.stroke(area.axis.path);
    area.axis.labels.forEach((label) => {
      ctx.fillText(label.text, label.x - 2, label.y);
    });
  }


  /**
   *  An array of trace ids to highlight. Set to [] to remove all highlighting.
   */
  get highlight(): string[] {
    return Object.keys(this._highlighted);
  }

  set highlight(ids: string[]) {
    this._highlighted = {};
    ids.forEach((name) => {
      this._highlighted[name] = true;
    });
    this._drawOverlayCanvas();
  }

  /**
   * Location to put a vertical marking bar on the graph. Can be set to -1 to
   * not display any bar.
   */
  get xbar(): number {
    return this._xbar;
  }

  set xbar(value: number) {
    this._xbar = value;
    this._drawOverlayCanvas();
  }


  /**
   * A list of x source offsets to place vertical markers. into labels. Can be
   *   set to [] to remove all bands.
   */
  get bands(): number[] {
    return this._bands;
  }

  set bands(bands: number[]) {
    if (!bands) {
      this._bands = [];
    } else {
      this._bands = bands;
    }
    this._drawOverlayCanvas();
  }

  /** The zoom range, an array of two values in source x units. Can be set to
   * null to have no zoom.
   */
  get zoom(): ZoomRange {
    return this._zoom;
  }

  set zoom(range: ZoomRange) {
    this._zoom = range;
    if (this._zoomTask) {
      return;
    }
    this._zoomTask = window.setTimeout(() => this._zoomImpl());
  }

  private _zoomImpl() {
    this._updateScaleDomains();
    this._recalcDetailPaths();
    this._drawTracesCanvas();
    this._zoomTask = 0;
  }

  static get observedAttributes(): string[] {
    return ['width', 'height', 'summary'];
  }

  /** Mirrors the width attribute. */
  get width(): number {
    return +(this.getAttribute('width') || '0');
  }

  set width(val: number) {
    this.setAttribute('width', val.toString());
  }

  /** Mirrors the height attribute. */
  get height(): number {
    return +(this.getAttribute('height') || '0');
  }

  set height(val: number) {
    this.setAttribute('height', val.toString());
  }

  /** @prop summary {string} Mirrors the summary attribute. */
  get summary(): boolean {
    return this.hasAttribute('summary');
  }

  set summary(val: boolean) {
    if (val) {
      this.setAttribute('summary', val.toString());
    } else {
      this.removeAttribute('summary');
    }
  }
}

define('plot-simple-sk', PlotSimpleSk);
