// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {CustomElement} from 'chrome://resources/js/custom_element.js';

import type {Signals} from '../omnibox_internals.mojom-webui.js';
import {clamp, signalNames} from '../omnibox_util.js';

import type {MlBrowserProxy} from './ml_browser_proxy.js';
import sheet from './ml_chart.css' with {type : 'css'};
import {getTemplate} from './ml_chart.html.js';

// Represents a line of text when drawing multiline text onto the canvas.
interface TextLine {
  text: string;
  color: string;
  fontSize: number;
  bold: boolean;
}

// Represents a single point when drawing a line plot onto the canvas.
interface PlotPoint {
  position: Vector;
  label: TextLine[];
}

// Represents a line plot to be drawn onto the canvas.
interface Plot {
  points: PlotPoint[];
  label: string;
  color: string;
  xAxisLabel: string;
  xAxisOffset: number;
  xAxisScale: number;
}

// Helps do vector math.
class Vector {
  x: number;
  y: number;

  constructor(x: number = 0, y: number = x) {
    this.x = x;
    this.y = y;
  }

  get array(): [number, number] {
    return [this.x, this.y];
  }

  setX(x: number) {
    return new Vector(x, this.y);
  }

  setY(y: number) {
    return new Vector(this.x, y);
  }

  add(v: Vector) {
    return new Vector(this.x + v.x, this.y + v.y);
  }

  subtract(v: Vector) {
    return this.add(v.negate());
  }

  pointwiseMultiply(v: Vector) {
    return new Vector(this.x * v.x, this.y * v.y);
  }

  pointwiseDivide(v: Vector) {
    return new Vector(this.x / v.x, this.y / v.y);
  }

  scale(scaler: number) {
    return this.pointwiseMultiply(new Vector(scaler));
  }

  negate() {
    return this.scale(-1);
  }

  // Useful because the canvas coordinates has y=0 at the top, but grid
  // coordinates has y=0 at the bottom.
  invertY(maxY: number) {
    return this.setY(maxY - this.y);
  }

  magnitudeSqr() {
    return this.x ** 2 + this.y ** 2;
  }

  clamp(min: Vector, max: Vector) {
    return new Vector(clamp(this.x, min.x, max.x), clamp(this.y, min.y, max.y));
  }

  // Transforms from coordinate system to another. Canvas <-> grid coordinates.
  transform(
      oldOrigin: Vector, oldSize: Vector, newOrigin: Vector, newSize: Vector) {
    return this.subtract(oldOrigin)
        .transformScale(oldSize, newSize)
        .add(newOrigin);
  }

  transformScale(oldSize: Vector, newSize: Vector) {
    return this.pointwiseDivide(oldSize).pointwiseMultiply(newSize);
  }
}

export class MlChartElement extends CustomElement {
  private mlBrowserProxy_: MlBrowserProxy;
  private signals_: Signals;
  private plots: Plot[] = [];

  private context: CanvasRenderingContext2D;

  private readonly clearColor = this.getCssProperty('--theme');
  private readonly primaryColor = this.getCssProperty('--text');

  private canvasSize: Vector;
  private readonly axisPadding =
      new Vector(50);        // Padding between canvas border and axes lines.
  private gridMin: Vector;   // The grid coordinate of the axes origin.
  private gridSize: Vector;  // The grid lengths of the axes.

  private mouseDown: boolean = false;  // Whether a mouse button is down.
  private mousePosition: Vector;       // Canvas coordinates of the mouse.

  static override get template() {
    return getTemplate();
  }

  constructor() {
    super();
    this.shadowRoot!.adoptedStyleSheets = [sheet];
  }

  connectedCallback() {
    const canvas = this.getRequiredElement('canvas');
    this.canvasSize = new Vector(canvas.width, canvas.height);
    this.context = canvas.getContext('2d')!;
    canvas.addEventListener(
        'mousemove',
        e => this.onMouseMove(e.buttons > 0, new Vector(e.offsetX, e.offsetY)));
    canvas.addEventListener('wheel', e => {
      e.preventDefault();
      this.onMouseWheel(new Vector(e.offsetX, e.offsetY), Math.sign(e.deltaY));
    });
  }

  set mlBrowserProxy(mlBrowserProxy: MlBrowserProxy) {
    this.mlBrowserProxy_ = mlBrowserProxy;
  }

  set signals(signals: Signals) {
    this.plots = [];
    this.clear();

    this.signals_ = signals;

    // Set grid [-15, 0] and [15, 1] to line up with the axes' starts and ends.
    this.gridSize = new Vector(30, 1)
                        .pointwiseMultiply(this.canvasSize)
                        .pointwiseDivide(this.canvasSize.subtract(
                            this.axisPadding.scale(2)));
    // Subtract half the gridSize from the grid center.
    this.gridMin = new Vector(0, .5).subtract(this.gridSize.scale(.5));

    this.createPlots();
  }

  private async createPlots() {
    if (!this.signals_ || !this.mlBrowserProxy_) {
      return;
    }

    // Only graph the 1st 4 signals, since those happen to be the one's we're
    // interested in most often.
    const chartSignalNames = signalNames.slice(0, 4);

    // If there are more than `colors.length` plots, colors will be repeated.
    const colors = [
      this.getColor(0),    // red
      this.getColor(120),  // green
      this.getColor(240),  // blue
      this.getColor(300),  // pink
    ];

    const minX = Math.floor(this.gridMin.x);
    const maxX = Math.ceil(this.gridMin.add(this.gridSize).x);
    const xValues = [...Array(maxX - minX + 1)].map((_, j) => minX + j);

    interface MlRequest {
      x: number;
      scale: number;
      modifiedSignals: Signals;
      score: number;
    }
    const mlRequestPromises: Array<Array<Promise<MlRequest>>> =
        chartSignalNames.map(signalName => {
          const signal = this.signals_[signalName];
          // For signals such as elapsedTimeLastVisitSecs, it's sometimes
          // more useful to visualize on a zoomed-out x-axis. When their values
          // are small though, we still want to use the normal scale so we can
          // see patterns like score humps that tend to be in the 1-100 range.
          // So zoom-out based on the signal value; when the signal is [0-99]
          // scale is 1; when the signal is [100, 999], scale by 10; etc.
          const scale =
              (typeof signal === 'number' || typeof signal === 'bigint') ?
              10 ** Math.max(Math.floor(Math.log10(Number(signal)) - 1), 0) :
              1;
          return xValues
              .map((x): [number, number] => [x, Number(signal) + x * scale])
              .filter(([_, modifiedSignal]) => modifiedSignal > 0)
              .map(async([x, modifiedSignal]): Promise<MlRequest> => {
                const modifiedSignals = {
                  ...this.signals_,
                  [signalName]: modifiedSignal,
                };
                const score =
                    await this.mlBrowserProxy_.makeMlRequest(modifiedSignals);
                return {x, scale, modifiedSignals, score};
              });
        });
    const mlRequests: MlRequest[][] = await Promise.all(
        mlRequestPromises.map(arrayOfPromises => Promise.all(arrayOfPromises)));

    this.plots = chartSignalNames.map((signalName, i): Plot => {
      return {
        points: mlRequests[i]!.map(
            (mlRequest):
                PlotPoint => {
                  return {
                    position: new Vector(mlRequest.x, mlRequest.score),
                    label: [
                      ...chartSignalNames.map(
                          (signalName2, k): TextLine => ({
                            text: `${signalName2}: ${
                                Number(mlRequest.modifiedSignals[signalName2]!)
                                    .toLocaleString('en-US')}`,
                            color: colors[k % colors.length]!,
                            fontSize: 12,
                            bold: signalName2 === signalName,
                          })),
                      {
                        text: `Score: ${mlRequest.score.toFixed(3)}`,
                        color: this.primaryColor,
                        fontSize: 12,
                        bold: true,
                      },
                    ],
                  };
                }),
        label: signalName,
        color: colors[i % colors.length]!,
        xAxisLabel: signalName,
        xAxisOffset: Number(this.signals_[signalName]),
        xAxisScale: mlRequests[i]![0]?.scale || 1,
      };
    });

    this.draw();
  }

  private onMouseMove(mouseDown: boolean, position: Vector) {
    if (!this.plots.length) {
      return;
    }
    // If dragging the mouse, pan the grid.
    if (this.mouseDown && mouseDown) {
      this.gridMin = this.gridMin.subtract(
          this.invWh(position.subtract(this.mousePosition)));
      this.createPlots();
    }
    this.mouseDown = mouseDown;
    this.mousePosition = position;
    this.draw(position);
  }

  private onMouseWheel(position: Vector, zoom: number) {
    if (!this.plots.length) {
      return;
    }
    // Pan towards the mouse.
    const weight = .1;
    const oldGridCenter = this.gridMin.add(this.gridSize.scale(.5));
    const newGridCenter = this.invXy(position).scale(weight).add(
        oldGridCenter.scale((1 - weight)));
    // Zoom in/out by 15%.
    this.gridSize = this.gridSize.scale(1 + .15 * zoom);
    this.gridMin = newGridCenter.subtract(this.gridSize.scale(.5));
    this.draw(position);
    this.createPlots();
  }

  private draw(mouse: Vector|null = null) {
    this.clear();
    if (!this.plots.length) {
      return;
    }

    // Find which plot, if any, the mouse is hovering nearest.
    let closestDistance = 900;  // If the mouse is within 30px.
    let closestPlot: Plot|null = null;
    let closestPoint: PlotPoint|null = null;
    if (mouse) {
      this.plots.forEach(plot => plot.points.forEach(point => {
        const distance = this.xy(point.position).subtract(mouse).magnitudeSqr();
        if (distance < closestDistance) {
          closestDistance = distance;
          closestPlot = plot;
          closestPoint = point;
        }
      }));
    }
    // Typescript weirdness.
    if (closestPlot) {
      closestPlot = closestPlot as Plot;
    }

    // Draw the axes.
    const axisOrigin = this.axisPadding.invertY(this.canvasSize.y);
    const axisLength =
        this.canvasSize.subtract(this.axisPadding.scale(2)).invertY(0);
    const tickLength = new Vector(15);
    const labelOffset = new Vector(20);
    const nTicks = 5;
    const xAxisColor = closestPlot ? closestPlot.color : this.primaryColor;
    // Draw the axes ticks and tick labels.
    for (let i = 0; i <= nTicks; i++) {
      const tick = axisOrigin.add(axisLength.scale(i / nTicks));
      const tickGrid = this.invXy(tick);
      this.drawLine(
          tick.setY(axisOrigin.subtract(tickLength.scale(.5)).y),
          tickLength.setX(0), 1, xAxisColor);
      if (closestPlot) {
        const tickLabel =
            (tickGrid.x * closestPlot.xAxisScale + closestPlot.xAxisOffset)
                .toLocaleString(
                    'en-US',
                    {minimumFractionDigits: 1, maximumFractionDigits: 1});
        this.drawText(
            tickLabel, tick.setY(axisOrigin.add(labelOffset).y), xAxisColor, 12,
            false, 'center', 'middle');
      }
      this.drawLine(
          tick.setX(axisOrigin.subtract(tickLength.scale(.5)).x),
          tickLength.setY(0), 1, this.primaryColor);
      this.drawText(
          tickGrid.y.toFixed(2), tick.setX(axisOrigin.subtract(labelOffset).x),
          this.primaryColor, 12, false, 'center', 'middle');
    }
    this.drawLine(axisOrigin, axisLength.setY(0), 2, xAxisColor);
    this.drawLine(axisOrigin, axisLength.setX(0), 2, this.primaryColor);

    // Draw the axes titles.
    if (closestPlot) {
      this.drawText(
          closestPlot.xAxisLabel,
          axisOrigin.add(axisLength.scale(.5).setY(0))
              .add(labelOffset.scale(2).setX(0)),
          xAxisColor, 12, false, 'center', 'middle');
    }
    this.drawVertText(
        'Score',
        axisOrigin.add(axisLength.scale(.5).setX(0))
            .add(labelOffset.scale(-2).setY(0)),
        this.primaryColor, 12, false, 'center', 'middle');

    // Draw the plots.
    this.plots.forEach(plot => plot.points.forEach((point, i, points) => {
      if (i) {
        const prev = points[i - 1]!;
        this.drawLine(
            this.xy(prev.position),
            this.wh(point.position.subtract(prev.position)),
            plot === closestPlot ? 3 : 1, plot.color);
      }
    }));

    // Draw the original signal.
    const centerPosition = this.plots.flatMap(plot => plot.points)
                               .map(point => point.position)
                               .find(position => !position.x);
    if (centerPosition) {
      this.drawPoint(this.xy(centerPosition), 7, this.primaryColor);
    }

    // Draw the legend.
    this.drawMultilineText(
        this.plots.map(plot => ({
                         text: plot.label,
                         color: plot.color,
                         fontSize: 12,
                         bold: plot === closestPlot,
                       })),
        this.canvasSize.setY(0), this.clearColor, this.clearColor, 'right');

    // Draw the tooltip if the mouse is hovering near a plot.
    if (closestPlot) {
      this.drawPoint(this.xy(closestPoint!.position), 7, closestPlot.color);
      this.drawMultilineText(
          closestPoint!.label, mouse!.add(labelOffset), closestPlot.color,
          this.clearColor, 'left');
    }
  }

  private clear() {
    this.drawRect(new Vector(), this.canvasSize, 0, this.clearColor);
  }

  // Draws a filled square centered at `xy` with side length `size`.
  private drawPoint(xy: Vector, size: number, color: string) {
    const sizeV = new Vector(size);
    this.drawRect(xy.subtract(sizeV.scale(.5)), sizeV, 0, color);
  }

  // Draws a line from `xy` to `xy+wh`. `lineWidth` is in canvas units (pixels).
  private drawLine(xy: Vector, wh: Vector, lineWidth: number, color: string) {
    this.context.lineWidth = lineWidth;
    this.context.strokeStyle = color;
    this.context.beginPath();
    this.context.moveTo(...xy.array);
    this.context.lineTo(...xy.add(wh).array);
    this.context.stroke();
  }

  // Draws a rect, either outline-only or filled depending on if `lineWidth` is
  // given. `lineWidth` is in canvas units (pixels).
  private drawRect(xy: Vector, wh: Vector, lineWidth: number, color: string) {
    if (lineWidth) {
      this.context.lineWidth = lineWidth;
      this.context.strokeStyle = color;
      this.context.strokeRect(...xy.array, ...wh.array);
    } else {
      this.context.fillStyle = color;
      this.context.fillRect(...xy.array, ...wh.array);
    }
  }

  // `fontSize` is in canvas units (pixels).
  private drawText(
      text: string, xy: Vector, color: string, fontSize: number, bold: boolean,
      horizAlign: CanvasTextAlign, vertAlign: CanvasTextBaseline) {
    this.context.fillStyle = color;
    this.setFont(fontSize, bold);
    this.context.textAlign = horizAlign;
    this.context.textBaseline = vertAlign;
    this.context.fillText(text, ...xy.array);
  }

  // Draws text rotated 90deg counter clockwise. `fontSize` is in canvas units
  // (pixels).
  private drawVertText(
      text: string, xy: Vector, color: string, fontSize: number, bold: boolean,
      horizAlign: CanvasTextAlign, vertAlign: CanvasTextBaseline) {
    this.context.translate(...xy.array);
    this.context.rotate(-Math.PI / 2);
    this.context.translate(...xy.negate().array);
    this.drawText(text, xy, color, fontSize, bold, horizAlign, vertAlign);
    this.context.resetTransform();
  }

  // Draws a rectangle background, then draws text over it. Each line of text
  // can have different font, color, and style. `outlineColor` and
  // `backgroundColor` affect the rectangle only. The rectangle dimensions are
  // auto-computed to fit the text. The position `xy` will be adjusted to ensure
  // all the text fits on the canvas if possible.
  private drawMultilineText(
      textLines: TextLine[], xy: Vector, outlineColor: string,
      backgroundColor: string, horizAlign: 'left'|'right') {
    const padding = 3;
    const lineWh: Array<[number, number]> = textLines.map(textLine => {
      this.setFont(textLine.fontSize, textLine.bold);
      const m = this.context.measureText(textLine.text);
      return [m.width, m.fontBoundingBoxAscent + m.fontBoundingBoxDescent];
    });
    const textWidth = Math.max(...lineWh.map(wh => wh[0]));
    const textHeights = lineWh.map(wh => wh[1]);
    const rectSize = new Vector(
        textWidth + padding * 2,
        textHeights.reduce((sum, height) => sum + height, 0) + padding * 2);

    xy = xy.clamp(new Vector(), this.canvasSize.subtract(rectSize));

    this.drawRect(xy, rectSize, 0, backgroundColor);
    this.drawRect(xy, rectSize, 1, outlineColor);
    if (horizAlign === 'right') {
      xy = xy.add(new Vector(textWidth, 0));
    }
    xy = xy.add(new Vector(padding));
    textLines.forEach((textLine, i) => {
      this.drawText(
          textLine.text, xy, textLine.color, textLine.fontSize, textLine.bold,
          horizAlign, 'top');
      xy.y += textHeights[i]!;
    });
  }

  // Converts grid coordinates to canvas coordinates. E.g. [1, 1] -> [600, 0].
  private xy(v: Vector) {
    return v.transform(
        this.gridMin, this.gridSize, this.canvasSize.setX(0),
        this.canvasSize.invertY(0));
  }

  // Converts grid distances to canvas distances. E.g. [1, 1] -> [600, 600].
  private wh(v: Vector): Vector {
    return v.transformScale(this.gridSize, this.canvasSize.invertY(0));
  }

  // Converts canvas coordinates to grid coordinates. E.g. [600, 600] -> [1, 0].
  private invXy(v: Vector): Vector {
    return v.transform(
        this.canvasSize.setX(0), this.canvasSize.invertY(0), this.gridMin,
        this.gridSize);
  }

  // Converts canvas distances to grid distances. E.g. [600, 600] -> [1, 1].
  private invWh(v: Vector): Vector {
    return v.transformScale(this.canvasSize.invertY(0), this.gridSize);
  }

  private setFont(fontSize: number, bold: boolean) {
    this.context.font = `${bold ? 'bold' : ''} ${fontSize}px arial`;
  }

  // Helper to read css variables like `var(--property)` defined in ml.css.
  private getCssProperty(property: string) {
    return getComputedStyle(this).getPropertyValue(property);
  }

  // Helper to get colors consistent with the colored texts defined in ml.css.
  private getColor(h: number) {
    return `hsl(${h}, 50%, ${this.getCssProperty('--color-lightness')})`;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'ml-chart': MlChartElement;
  }
}

customElements.define('ml-chart', MlChartElement);
