export type PhoneViewportRect = {
  bottom: number
  height: number
  left: number
  right: number
  top: number
  width: number
}

type RectMeasurement = Pick<
  DOMRectReadOnly,
  'height' | 'left' | 'top' | 'width'
>

export type PhoneViewportGeometry = {
  readonly scaleX: number
  readonly scaleY: number
  rect(element: Element): PhoneViewportRect
}

function positiveRatio(numerator: number, denominator: number): number {
  return Number.isFinite(numerator) &&
    Number.isFinite(denominator) &&
    numerator > 0 &&
    denominator > 0
    ? numerator / denominator
    : 1
}

export function normalizePhoneViewportRect(
  rawRect: RectMeasurement,
  rawCanvasRect: RectMeasurement,
  wrapperRect: RectMeasurement,
): PhoneViewportRect {
  const factorX = positiveRatio(wrapperRect.width, rawCanvasRect.width)
  const factorY = positiveRatio(wrapperRect.height, rawCanvasRect.height)
  const left = wrapperRect.left + (rawRect.left - rawCanvasRect.left) * factorX
  const top = wrapperRect.top + (rawRect.top - rawCanvasRect.top) * factorY
  const width = rawRect.width * factorX
  const height = rawRect.height * factorY

  return {
    bottom: top + height,
    height,
    left,
    right: left + width,
    top,
    width,
  }
}

export function readPhoneViewportGeometry(
  anchor: Element | null,
): PhoneViewportGeometry | null {
  const canvas = anchor?.closest<HTMLElement>('.phone-resolution-canvas')
  const wrapper = canvas?.closest<HTMLElement>('.phone-resolution-wrapper')
  if (!canvas || !wrapper) return null

  const rawCanvasRect = canvas.getBoundingClientRect()
  const wrapperRect = wrapper.getBoundingClientRect()

  return {
    scaleX: positiveRatio(wrapperRect.width, canvas.offsetWidth),
    scaleY: positiveRatio(wrapperRect.height, canvas.offsetHeight),
    rect(element: Element): PhoneViewportRect {
      return normalizePhoneViewportRect(
        element.getBoundingClientRect(),
        rawCanvasRect,
        wrapperRect,
      )
    },
  }
}
