/**
 * @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 { html } from 'lit/html.js';
import * as d3Scale from 'd3-scale';
import * as d3Array from 'd3-array';
import { Anomaly } from '../json';
import { define } from '../../../elements-sk/modules/define';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { KDTree, KDPoint } from './kd';
import { tick } from './ticks';
import { MISSING_DATA_SENTINEL } from '../const/const';
import { defaultColors } from '../common/plot-builder';
import { IssueDetail, UserIssueMap } from '../dataframe/dataframe_context';

//  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';

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

const MIN_MOUSE_MOVE_FOR_ZOOM = 5; // px

// Contains linear scales to convert from source coordinates into
// device/destination coordinates.
export 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,
    };
  }
}

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

const invalidPoint: Point = {
  x: Number.MIN_SAFE_INTEGER,
  y: Number.MIN_SAFE_INTEGER,
};

const pointIsValid = (p: Point): boolean => p.x !== invalidPoint.x;

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

/**
 * Convert rect in domain units into canvas coordinates using the given range.
 *
 * Presumes the rect was previously gotten from rectFromRangeInvert, so we don't
 * need to flip top and bottom.
 */
export const rectFromRange = (range: Range, rect: Rect): Rect => {
  const cleft = range.x(rect.x);
  const ctop = range.y(rect.y);
  const cright = range.x(rect.x + rect.width);
  const cbottom = range.y(rect.y + rect.height);
  return {
    x: cleft,
    y: ctop,
    width: cright - cleft,
    height: cbottom - ctop,
  };
};

/**
 * Convert rect in canvas units into domain units given the given range.
 *
 * Presumes this comes from a dragged out mouse region, which could be backwards
 * and/or upside down, so corrections are done to the corners.
 */
export const rectFromRangeInvert = (range: Range, rect: Rect): Rect => {
  let left = rect.x;
  let top = rect.y;
  let right = rect.x + rect.width;
  let bottom = rect.y + rect.height;
  if (right < left) {
    [left, right] = [right, left];
  }
  // We do this backwards since range.y then does a second direction reversal,
  // i.e. Canvas y-axis is in the opposite direction of the y-axis we use in
  // the data units.
  if (top < bottom) {
    [bottom, top] = [top, bottom];
  }

  return {
    x: range.x.invert(left),
    y: range.y.invert(top),
    width: range.x.invert(right) - range.x.invert(left),
    height: range.y.invert(bottom) - range.y.invert(top),
  };
};

const defaultRect: Rect = {
  x: 0,
  y: 0,
  width: 0,
  height: 0,
};

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;
}

export interface AnomalyData {
  x: number;
  y: number;
  anomaly: Anomaly;
  highlight: boolean;
}

export 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.
export 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.
export type ZoomRange = [number, number] | null;

// Used for both the trace_selected and trace_focused events.
export interface PlotSimpleSkTraceEventDetails {
  x: number;
  y: number;
  // DOM position of x in Pixels
  xPos?: number;
  // DOM position of y in Pixels
  yPos?: number;
  // The trace id.
  name: string;
}

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

/**
 * The type of zoom being done, or 'no-zoom' if no zoom is currently being done.
 */
export type ZoomDragType = 'no-zoom' | 'details' | 'summary';

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

  /** If true then draw dots on the traces. */
  private _dots: boolean = true;

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

  private _anomalyDataMap: { [key: string]: AnomalyData[] } = {};

  private _userIssueMap: { [key: string]: { [key: number]: IssueDetail } } = {};

  private _showCrosshairLabel: boolean = true;

  /** 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 tick objects the same length as the values in lineData. */
  private labels: tick[] = [];

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

  /** The source coordinate where a zoom started. */
  private zoomBegin: number = 0;

  /** The zoom rectangle on the details region. Stored in destination units. */
  private zoomRect: Rect = defaultRect;

  /**
   * detailsZoomRangesStack and inactiveZoomRangesStack work together to manage
   * a stack of zoom levels. As new zoom ranges are dragged out they are pushed
   * onto detailsZoomRangesStack, and as the mouse wheel is turned we push/pop
   * zoom ranges between detailsZoomRangesStack and inactiveZoomRangesStack.
   *
   * When plotting we only look at the top of the active stack, i.e. the end of
   * detailsZoomRangesStack.
   *
   * detailsZoomRangesStack is a stack of zoom ranges, each zoom range in the
   * stack represents a smaller area than the zoom range below it on the stack.
   * Zoom ranges are stored in domain units.
   */
  private detailsZoomRangesStack: Rect[] = [];

  /**
   * As we use the mouse wheel to move through zooms we store the ones we've
   * popped off of detailsZoomRangesStack here.
   *
   * Zoom ranges are stored in domain units.
   */
  private inactiveDetailsZoomRangesStack: Rect[] = [];

  /**
   * True if we are currently drag zooming, i.e. the mouse is pressed and moving
   * over the summary.
   */
  private inZoomDrag: ZoomDragType = 'no-zoom';

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

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

  /** The window.devicePixelRatio. */
  private scale: number = 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.
   */
  private mouseMoveRaw: MouseMoveRaw | null = 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 = 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 = {
    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.
   * }
   */
  private crosshair: CrosshairPoint = {
    x: -1,
    y: -1,
    shift: false,
  };

  /** All the info we need about the summary area. */
  private summaryArea: SummaryArea = {
    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. */
  private detailArea: DetailArea = {
    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(),
    },
  };

  /**
   * 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 = 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.
   */
  private zoomTask: number = 0;

  /**
   * A formatter that prints numbers nicely, such as adding commas. Used when
   * display the hover text.
   */
  private numberFormatter: Intl.NumberFormat = new 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 ANOMALY_BACKGROUND!: string; // CSS color.

  private ANOMALY_HIGHLIGHT_COLOR!: string; // CSS color.

  private UNTRIAGED_COLOR!: string; // CSS color.

  private REGRESSION_COLOR!: string; // CSS color.

  private IMPROVEMENT_COLOR!: string; // CSS color.

  private ANOMALY_RADIUS!: number; // px

  private ANOMALY_FONT_SIZE!: number; // px

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

  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);

    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();

    const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
      // We add this to avoid resizeObserver loop limit errors in unit tests
      // https://stackoverflow.com/a/58701523
      window.requestAnimationFrame(() => {
        if (!Array.isArray(entries) || !entries.length) {
          return;
        }
        // We need to dynamically resize the canvas elements since they don't do
        // that themselves.
        entries.forEach((entry) => {
          this.width = entry.contentRect.width;
          this.height = entry.contentRect.height;
        });
      });
    });
    resizeObserver.observe(this);

    this.addEventListener('mousemove', (e: MouseEvent) => {
      // 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: MouseEvent) => {
      e.preventDefault();
      const pt = this.eventToCanvasPt(e);
      // If you click in the summary area then begin zooming via drag.
      if (inRect(pt, this.summaryArea.rect!)) {
        const zx = this.summaryArea.range.x.invert(pt.x);
        this.inZoomDrag = 'summary';
        this.zoomBegin = zx;
        this.zoom = [zx, zx + 0.01]; // Add a smidge to the second zx to avoid a degenerate detail plot.

        // Zooming via the summary area clears all details area zooms.
        this.detailsZoomRangesStack = [];
        this.inactiveDetailsZoomRangesStack = [];
      }
      if (inRect(pt, this.detailArea.rect!)) {
        this.inZoomDrag = 'details';
        this.zoomRect = {
          x: pt.x,
          y: pt.y,
          width: 0,
          height: 0,
        };
      }
    });

    this.addEventListener('mouseup', (e: MouseEvent) => {
      e.preventDefault();
      if (this.inZoomDrag !== 'no-zoom') {
        this.dispatchZoomEvent();
      }
      if (this.inZoomDrag === 'details') {
        this.doDetailsZoom();
      }
      this.inZoomDrag = 'no-zoom';
    });

    this.addEventListener('mouseleave', (e: MouseEvent) => {
      e.preventDefault();
      if (this.inZoomDrag !== 'no-zoom') {
        this.dispatchZoomEvent();
      }
      if (this.inZoomDrag === 'details') {
        this.doDetailsZoom();
      }
      this.inZoomDrag = 'no-zoom';
    });

    this.addEventListener('click', (e) => {
      const pt = this.eventToCanvasPt(e);
      if (!inRect(pt, this.detailArea.rect)) {
        return;
      }
      if (!this.pointSearch) {
        return;
      }
      const closest = this.pointSearch.nearest(pt);
      const detail = {
        x: closest.sx,
        y: closest.sy,
        xPos: closest.x / this.scale,
        yPos: closest.y / this.scale,
        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: tick[]): void {
    const keys = Object.keys(lines);
    if (keys.length === 0) {
      return;
    }
    const startedEmpty = this._zoom === null && this.lineData.length === 0;
    if (labels.length > 0) {
      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. Make a copy so the NaN's
      // don't migrate out of plot-simple.
      const values = [...lines[key]!];
      values.forEach((x, i) => {
        if (x === MISSING_DATA_SENTINEL) {
          values[i] = NaN;
        }
      });

      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.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);
    if (this.anomalyDataMap !== null) {
      ids.forEach((id) => {
        if (id in this.anomalyDataMap) {
          delete this.anomalyDataMap[id];
        }
      });
    }
    const onlySpecialLinesRemaining = this.lineData.every((line) => line.name.startsWith(SPECIAL));
    if (onlySpecialLinesRemaining) {
      this.removeAll();
    } else {
      this.updateScaleDomains();
      this.recalcSummaryPaths();
      this.recalcDetailPaths();
      this.drawTracesCanvas();
    }
  }

  /**
   * Remove all lines from plot.
   */
  removeAll(): void {
    this.lineData = [];
    this.anomalyDataMap = {};
    this.labels = [];
    this.highlight = [];
    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 = 'no-zoom';
    this.detailsZoomRangesStack = [];
    this.inactiveDetailsZoomRangesStack = [];
    this.drawTracesCanvas();
  }

  /**
   * Return the names of all the lines being plotted, not including SPECIAL
   * names.
   * */
  getLineNames(): string[] {
    const ret: string[] = [];
    this.lineData.forEach((line) => {
      if (line.name.startsWith(SPECIAL)) {
        return;
      }
      ret.push(line.name);
    });
    return ret;
  }

  /**
   * 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.ANOMALY_RADIUS = 12 * this.scale; // px

    this.ANOMALY_FONT_SIZE = 26 * this.scale;

    this.ANOMALY_FONT = `${this.ANOMALY_FONT_SIZE}px Material Icons`;

    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;

    this.ANOMALY_BACKGROUND = style.getPropertyValue('--on-surface');
    this.UNTRIAGED_COLOR = style.getPropertyValue('--surface');
    this.IMPROVEMENT_COLOR = style.getPropertyValue('--success');
    this.REGRESSION_COLOR = style.getPropertyValue('--failure');
    this.ANOMALY_HIGHLIGHT_COLOR = style.getPropertyValue('--warning');

    // 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 === 'no-zoom') {
      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,
          xPos: closest.x / this.scale,
          yPos: closest.y / this.scale,
          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.detailArea.rect);
      } else {
        this.crosshair = {
          x: this.detailArea.range.x(this.hoverPt.x),
          y: this.detailArea.range.y(this.hoverPt.y),
          shift: true,
        };
      }
      this.drawOverlayCanvas();
    } else {
      // We are zooming.
      const pt = this.eventToCanvasPt(this.mouseMoveRaw);

      if (this.inZoomDrag === 'summary') {
        clampToRect(pt, this.summaryArea.rect);

        // x in source coordinates.
        const sx = this.summaryArea.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;
      } else if (this.inZoomDrag === 'details') {
        clampToRect(pt, this.detailArea.rect);
        this.zoomRect.width = pt.x - this.zoomRect.x;
        this.zoomRect.height = pt.y - this.zoomRect.y;
        this.drawOverlayCanvas();
      }
    }
    this.mouseMoveRaw = null;
  }

  /**
   * 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);
  }

  // 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 = defaultColors[(this.hashString(line.name) % (defaultColors.length - 1)) + 1];
      }

      const summaryBuilder = new PathBuilder(
        this.summaryArea.range.x,
        this.summaryArea.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.summaryArea, this.labels, 0);
  }

  // Rebuilds our cache of Path2D objects we use for quick rendering.
  private recalcDetailPaths() {
    const domain = this.detailArea.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 = defaultColors[(this.hashString(line.name) % (defaultColors.length - 1)) + 1];
      }

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

      let previousPoint: Point = invalidPoint;
      let addedPointFromBeforeTheDomain = false;
      let addedPointFromAfterTheDomain = false;
      line.values.forEach((y, x) => {
        if (Number.isNaN(y)) {
          return;
        }
        // Always add in one point after the domain so we draw all visible line
        // segments.
        if (x > domain[1] && !addedPointFromAfterTheDomain) {
          detailBuilder.add(x, y);
          addedPointFromAfterTheDomain = true;
          return;
        }
        if (x < domain[0] || x > domain[1]) {
          previousPoint = { x: x, y: y };
          return;
        }
        // Always add in one point before the domain so we draw all visible line
        // segments.
        if (!addedPointFromBeforeTheDomain) {
          if (pointIsValid(previousPoint)) {
            detailBuilder.add(previousPoint.x, previousPoint.y);
          }
          addedPointFromBeforeTheDomain = true;
        }
        detailBuilder.add(x, y);
      });
      line.detail = detailBuilder.paths();
    });

    // Build detail x-axis.
    const detailDomain = this.detailArea.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.detailArea, detailLabels, labelOffset);

    // Build detail y-axis.
    this.recalcYAxis(this.detailArea);
    this.recalcSearch();
  }

  // Recalculates the y-axis info.
  private recalcYAxis(area: DetailArea) {
    const yAxisPath = new Path2D();
    const thinX = Math.floor(this.detailArea.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.detailArea.rect.y);
    yAxisPath.lineTo(thinX, this.detailArea.rect.y + this.detailArea.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: tick[], 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 = [];
    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.detailArea.range.x.domain();
    domain[0] = Math.floor(domain[0] - 0.1);
    domain[1] = Math.ceil(domain[1] + 0.1);
    const searchBuilder = new SearchBuilder(this.detailArea.range.x, this.detailArea.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.detailArea.range.x = this.detailArea.range.x.domain(this._zoom);
    } else {
      this.detailArea.range.x = this.detailArea.range.x.domain([0, domainEnd]);
    }

    this.summaryArea.range.x = this.summaryArea.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.detailArea.range.y = this.detailArea.range.y.domain(domain).nice();

    this.summaryArea.range.y = this.summaryArea.range.y.domain(domain);

    // If detailsZoomRangeStacks is not empty then it overrides the detail
    // range.
    if (this.detailsZoomRangesStack.length > 0) {
      const zoom = this.detailsZoomRangesStack[this.detailsZoomRangesStack.length - 1];
      this.detailArea.range.x = this.detailArea.range.x.domain([zoom.x, zoom.x + zoom.width]);
      this.detailArea.range.y = this.detailArea.range.y.domain([zoom.y, zoom.y + zoom.height]);
    }
  }

  // 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.summaryArea.range.x = this.summaryArea.range.x.range([
      this.LEFT_MARGIN,
      width - this.MARGIN,
    ]);

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

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

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

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

    this.detailArea.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,
    };
  }

  private doDetailsZoom() {
    // Don't actually do the zoom if the box isn't big enough.
    if (
      Math.abs(this.zoomRect.width) < MIN_MOUSE_MOVE_FOR_ZOOM ||
      Math.abs(this.zoomRect.height) < MIN_MOUSE_MOVE_FOR_ZOOM
    ) {
      return;
    }
    this.detailsZoomRangesStack.push(rectFromRangeInvert(this.detailArea.range, this.zoomRect));

    // We added a new zoom range, which means all the inactive zoom ranges are
    // no longer valid.
    this.inactiveDetailsZoomRangesStack = [];
    this.inZoomDrag = 'no-zoom';
    this._zoomImpl();
  }

  // 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.summaryArea.rect);

        // Draw the xbar.
        this.drawXBar(ctx, this.summaryArea, this.SUMMARY_BAR_WIDTH);

        // Draw the bands.
        this.drawBands(ctx, this.summaryArea, this.SUMMARY_BAR_WIDTH);

        // If detailsZoomRangeStacks is not empty then draw a box to indicate
        // the zoomed region.
        if (this.detailsZoomRangesStack.length > 0) {
          const zoom = this.detailsZoomRangesStack[this.detailsZoomRangesStack.length - 1];
          this.drawZoomRect(ctx, rectFromRange(this.summaryArea.range, zoom));
        }

        // 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.summaryArea.range.x(this._zoom[0]);
          ctx.beginPath();
          ctx.moveTo(leftx, this.summaryArea.rect.y);
          ctx.lineTo(leftx, this.summaryArea.rect.y + this.summaryArea.rect.height);

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

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

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

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

      // Draw the xbar.
      this.drawXBar(ctx, this.detailArea, this.DETAIL_BAR_WIDTH);

      // Draw the bands.
      this.drawBands(ctx, this.detailArea, 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!);
        if (this.dots) {
          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.
        if (this.dots) {
          ctx.fill(line.detail.dotsPath!);
          ctx.stroke(line.detail.dotsPath!);
        }
      }

      this.drawUserIssues(ctx, this.detailArea);

      // Draw the anomalies.
      this.drawAnomalies(ctx, this.detailArea);

      if (this.inZoomDrag === 'details') {
        this.drawZoomRect(ctx, this.zoomRect);
      } else if (this.inZoomDrag === 'no-zoom') {
        // 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.detailArea.rect.x, thinY);
        ctx.lineTo(this.detailArea.rect.x + this.detailArea.rect.width, thinY);
        ctx.moveTo(thinX, this.detailArea.rect.y);
        ctx.lineTo(thinX, this.detailArea.rect.y + this.detailArea.rect.height);
        ctx.stroke();

        // Y label at crosshair if shift is pressed.
        if (this.showCrosshairLabel && this.crosshair.shift) {
          // Draw the label offset from the crosshair.
          ctx.font = this.LABEL_FONT;
          ctx.textBaseline = 'bottom';
          ctx.textAlign = 'start';
          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.detailArea.rect.y + this.detailArea.rect.height / 2) {
            y = this.crosshair.y + this.MARGIN;
          }
          if (x > this.detailArea.rect.x + this.detailArea.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 a dashed rectangle for the details zoom.
  private drawZoomRect(ctx: CanvasRenderingContext2D, rect: Rect) {
    ctx.strokeStyle = this.LABEL_COLOR;
    ctx.lineWidth = 1;
    ctx.setLineDash([2, 2]);
    ctx.strokeRect(rect.x, rect.y, rect.width, rect.height);
    ctx.setLineDash([]);
  }

  // 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 all anomalies in the given area.
  private drawAnomalies(ctx: CanvasRenderingContext2D, area: Area) {
    const keys = Object.keys(this._anomalyDataMap);
    keys.forEach((key) => {
      this._anomalyDataMap[key].forEach((anomalyData) => {
        const anomaly = anomalyData.anomaly;

        // Anomaly is Ignored or marked as Invalid.
        if (anomaly.bug_id < 0 || anomaly.recovered) {
          ctx.globalAlpha = 0.5;
        } else {
          ctx.globalAlpha = 1.0;
        }

        const cx = area.range.x(anomalyData.x);
        const cy = area.range.y(anomalyData.y);
        const anomalyPath = new Path2D();

        // Draw white circle background of anomaly icon.
        anomalyPath.moveTo(cx + this.ANOMALY_RADIUS, cy);
        anomalyPath.arc(cx, cy, this.ANOMALY_RADIUS, 0, 2 * Math.PI);
        ctx.fillStyle = this.ANOMALY_BACKGROUND;

        ctx.fill(anomalyPath);

        // If the anomaly is marked for highlighting, draw a circle around
        // the icon with the highlight color.
        if (anomalyData.highlight) {
          const highlightPath = new Path2D();
          const highlightRadius = this.ANOMALY_RADIUS + 2 * this.scale;
          highlightPath.moveTo(cx + highlightRadius, cy);
          highlightPath.arc(cx, cy, highlightRadius, 0, 2 * Math.PI);

          ctx.fillStyle = this.ANOMALY_HIGHLIGHT_COLOR;
          ctx.fill(highlightPath);
        }

        if (anomaly.bug_id <= 0) {
          ctx.fillStyle = this.UNTRIAGED_COLOR;
        } else {
          ctx.fillStyle = anomaly.is_improvement ? this.IMPROVEMENT_COLOR : this.REGRESSION_COLOR;
        }

        const regression_symbol = String.fromCharCode(0xe000);
        const improvement_symbol = String.fromCharCode(0xe86c);
        const symbol = anomaly.is_improvement ? improvement_symbol : regression_symbol;

        // Draw anomaly icon.
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.font = this.ANOMALY_FONT;
        ctx.fillText(symbol, cx, cy);
      });
    });
  }

  // Draw all user issues in the given area.
  private drawUserIssues(ctx: CanvasRenderingContext2D, area: Area) {
    if (this.userIssueMap === null || this.userIssueMap === undefined) {
      return;
    }

    const keys = Object.keys(this._userIssueMap);
    keys.forEach((trace_key) => {
      Object.keys(this._userIssueMap[trace_key]).forEach((commit_position: string) => {
        const issue = this._userIssueMap[trace_key][parseInt(commit_position)];

        if (issue.bugId === 0) return;

        if (issue.x === -1 || issue.y === -1) {
          return;
        }

        // If point is an anomaly ignore the user issue
        // since the point is already highlighted
        let isAnomaly = false;
        const anomaliesOnTrace = this._anomalyDataMap[trace_key];
        if (anomaliesOnTrace !== null && anomaliesOnTrace !== undefined) {
          anomaliesOnTrace.forEach((a) => {
            if (a.x === issue.x && a.y === issue.y) {
              isAnomaly = true;
              return;
            }
          });
        }
        if (isAnomaly) {
          return;
        }

        ctx.globalAlpha = 0.5;
        const cx = area.range.x(issue.x);
        const cy = area.range.y(issue.y);
        const path = new Path2D();

        // Draw white circle background of anomaly icon.
        path.moveTo(cx + this.ANOMALY_RADIUS, cy);
        path.arc(cx, cy, this.ANOMALY_RADIUS, 0, 2 * Math.PI);
        ctx.fillStyle = this.ANOMALY_BACKGROUND;

        ctx.fill(path);
        ctx.fillStyle = this.UNTRIAGED_COLOR;

        const symbol = String.fromCharCode(0xe000);

        // Draw user issue icon.
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.font = this.ANOMALY_FONT;
        ctx.fillText(symbol, cx, cy);
      });
    });
  }

  // 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 !== 'no-zoom') {
      ctx.clearRect(
        this.detailArea.rect.x - this.MARGIN,
        this.detailArea.rect.y - this.MARGIN,
        this.detailArea.rect.width + 2 * this.MARGIN,
        this.detailArea.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.detailArea.rect);
      this.drawXAxis(ctx, this.detailArea);
      ctx.fillStyle = this.LABEL_BACKGROUND;

      this.lineData.forEach((line) => {
        ctx.strokeStyle = line.color;
        ctx.lineWidth = DETAIL_LINE_WIDTH;
        ctx.stroke(line.detail.linePath!);
        if (this.dots) {
          ctx.fill(line.detail.dotsPath!);
          ctx.stroke(line.detail.dotsPath!);
        }
      });
    }
    ctx.restore();
    this.drawXAxis(ctx, this.detailArea);

    if (this.inZoomDrag === 'no-zoom' && this.summary) {
      // Draw the summary.
      ctx.save();
      {
        // Block to scope save/restore.
        clipToRect(ctx, this.summaryArea.rect);
        this.lineData.forEach((line) => {
          ctx.fillStyle = this.LABEL_BACKGROUND;
          ctx.strokeStyle = line.color;
          ctx.lineWidth = SUMMARY_LINE_WIDTH;
          ctx.stroke(line.summary.linePath!);
          if (this.dots) {
            ctx.fill(line.summary.dotsPath!);
            ctx.stroke(line.summary.dotsPath!);
          }
        });
      }
      ctx.restore();
      this.drawXAxis(ctx, this.summaryArea);
    }
    // Draw y-Axes.
    this.drawYAxis(ctx, this.detailArea);

    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);
    });
  }

  /**
   * Helper to trigger re-draw of overlay canvas from parent element.
   */
  redrawOverlayCanvas() {
    this.drawOverlayCanvas();
  }

  /**
   *  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();
  }

  get anomalyDataMap(): { [key: string]: AnomalyData[] } {
    return this._anomalyDataMap;
  }

  set anomalyDataMap(anomalyDataMap: { [key: string]: AnomalyData[] }) {
    this._anomalyDataMap = anomalyDataMap;
    this.drawOverlayCanvas();
  }

  get userIssueMap(): UserIssueMap {
    return this._userIssueMap;
  }

  set userIssueMap(userIssueMap: UserIssueMap) {
    this._userIssueMap = userIssueMap || {};
    this.drawOverlayCanvas();
  }

  get showCrosshairLabel(): boolean {
    return this._showCrosshairLabel;
  }

  set showCrosshairLabel(show: boolean) {
    this._showCrosshairLabel = show;
  }

  /** 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');
    }
  }

  /** @prop nodots {boolean} Mirrors the nodots attribute.  */
  get dots(): boolean {
    return this._dots;
  }

  set dots(val: boolean) {
    this._dots = val;
    this.drawTracesCanvas();
  }
}

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