import {mat3} from 'gl-matrix';

import {FlamegraphTheme} from '../flamegraph/flamegraphTheme';
import {getContext, Rect} from '../gl/utils';

class PositionIndicatorRenderer {
  canvas: HTMLCanvasElement;
  context: CanvasRenderingContext2D;
  theme: FlamegraphTheme;

  constructor(canvas: HTMLCanvasElement, theme: FlamegraphTheme) {
    this.canvas = canvas;
    this.theme = theme;

    this.context = getContext(this.canvas, '2d');
  }

  draw(configView: Rect, configSpace: Rect, configSpaceToPhysicalSpace: mat3): void {
    if (configView.equals(configSpace)) {
      // User is not zoomed in or entire chart fits in view,
      // then we dont need to draw anything.
      return;
    }

    // Transform both views to their respective physical spaces
    const physicalConfigViewRect = Rect.From(configView).transformRect(
      configSpaceToPhysicalSpace
    );

    const physicalConfigRect = Rect.From(configSpace).transformRect(
      configSpaceToPhysicalSpace
    );

    const offsetRectForBorderWidth: [number, number, number, number] = [
      physicalConfigViewRect.x - this.theme.SIZES.MINIMAP_POSITION_OVERLAY_BORDER_WIDTH,
      physicalConfigViewRect.y,
      physicalConfigViewRect.width +
        this.theme.SIZES.MINIMAP_POSITION_OVERLAY_BORDER_WIDTH,
      physicalConfigViewRect.height,
    ];

    // What we do to draw the "window" that the user is currently watching is we draw two rectangles, the
    // zoomed in view and the zoomed out view. The zoomed out view is the full view of the flamegraph, and the zoom
    // in view is whatever the user is currently looking at. Because the zoomed in view is a subset of the zoomed,
    // we just need to use the evenodd fill rule to paint inbetween the two rectangles.
    this.context.fillStyle = this.theme.COLORS.MINIMAP_POSITION_OVERLAY_COLOR;
    this.context.strokeStyle = this.theme.COLORS.MINIMAP_POSITION_OVERLAY_BORDER_COLOR;
    this.context.lineWidth = this.theme.SIZES.MINIMAP_POSITION_OVERLAY_BORDER_WIDTH;

    this.context.beginPath();
    this.context.rect(0, 0, physicalConfigRect.width, physicalConfigRect.height);
    this.context.rect(...offsetRectForBorderWidth);

    this.context.fill('evenodd');
    this.context.strokeRect(...offsetRectForBorderWidth);
  }
}

export {PositionIndicatorRenderer};
