/**
 * Chart annotation drawing
 * @countermeasure/web-components/charts/annotations
 */

import type { PlotArea } from './types'

/** Describes an annotation to overlay on a chart */
export interface Annotation {
  type: 'hline' | 'vline' | 'region'
  /** Primary value: y-position for hline, x-position for vline, start value for region */
  value: number
  /** End value for region annotations */
  value2?: number
  color: string
  label?: string
  dashPattern?: number[]
}

const ANNOTATION_FONT = '11px system-ui, sans-serif'

/** Draw annotations on a chart canvas within the given plot area */
export function drawAnnotations(
  ctx: CanvasRenderingContext2D,
  plotArea: PlotArea,
  annotations: Annotation[],
  scaleX: (v: number) => number,
  scaleY: (v: number) => number
): void {
  const { x, y, width, height } = plotArea

  ctx.save()

  // Clip to plot area
  ctx.beginPath()
  ctx.rect(x, y, width, height)
  ctx.clip()

  for (const annotation of annotations) {
    ctx.strokeStyle = annotation.color
    ctx.fillStyle = annotation.color
    ctx.lineWidth = 1

    if (annotation.dashPattern !== undefined) {
      ctx.setLineDash(annotation.dashPattern)
    } else {
      ctx.setLineDash([4, 4])
    }

    if (annotation.type === 'hline') {
      const py = scaleY(annotation.value)
      ctx.beginPath()
      ctx.moveTo(x, py)
      ctx.lineTo(x + width, py)
      ctx.stroke()

      if (annotation.label !== undefined) {
        ctx.setLineDash([])
        ctx.font = ANNOTATION_FONT
        ctx.textAlign = 'left'
        ctx.textBaseline = 'bottom'
        ctx.fillText(annotation.label, x + 4, py - 3)
      }
    } else if (annotation.type === 'vline') {
      const px = scaleX(annotation.value)
      ctx.beginPath()
      ctx.moveTo(px, y)
      ctx.lineTo(px, y + height)
      ctx.stroke()

      if (annotation.label !== undefined) {
        ctx.setLineDash([])
        ctx.font = ANNOTATION_FONT
        ctx.textAlign = 'left'
        ctx.textBaseline = 'top'
        ctx.save()
        ctx.translate(px + 4, y + 4)
        ctx.fillText(annotation.label, 0, 0)
        ctx.restore()
      }
    } else {
      const x1 = scaleX(annotation.value)
      const x2 = annotation.value2 !== undefined ? scaleX(annotation.value2) : x + width

      ctx.setLineDash([])
      ctx.globalAlpha = 0.1
      ctx.fillRect(x1, y, x2 - x1, height)
      ctx.globalAlpha = 1.0

      // Region borders
      ctx.strokeStyle = annotation.color
      ctx.lineWidth = 1
      ctx.setLineDash([2, 2])
      ctx.beginPath()
      ctx.moveTo(x1, y)
      ctx.lineTo(x1, y + height)
      ctx.stroke()
      ctx.beginPath()
      ctx.moveTo(x2, y)
      ctx.lineTo(x2, y + height)
      ctx.stroke()

      if (annotation.label !== undefined) {
        ctx.setLineDash([])
        ctx.font = ANNOTATION_FONT
        ctx.textAlign = 'center'
        ctx.textBaseline = 'top'
        ctx.fillText(annotation.label, (x1 + x2) / 2, y + 4)
      }
    }

    ctx.setLineDash([])
  }

  ctx.restore()
}
