// Shortest-column masonry distribution (ported from ImageRepo).
//
// Predictive relative height = height / width. Using the aspect ratio means
// columns are balanced before thumbnails load, so there is no reflow when
// images arrive. Missing or zero dimensions fall back to a square (1.0).

import { ref, onMounted, onUnmounted } from 'vue'

function relativeHeight(item) {
  const w = Number(item.width)
  const h = Number(item.height)
  if (!w || !h) return 1
  return h / w
}

export function distributeIntoColumns(items, columnCount) {
  const n = Math.max(1, columnCount | 0)
  const columns = Array.from({ length: n }, () => [])
  const heights = new Array(n).fill(0)
  for (const item of items) {
    let shortest = 0
    for (let c = 1; c < n; c++) {
      if (heights[c] < heights[shortest]) shortest = c
    }
    columns[shortest].push(item)
    heights[shortest] += relativeHeight(item)
  }
  return columns
}

// Reactive column count from container width. Breakpoints mirror the
// gallery grid intent: ~390px target column width, min 1 column. Bumped
// from 260px on 2026-05-23 per dogfood UX feedback (thumbs were too small).
export function columnCountForWidth(width) {
  if (!width || width < 0) return 1
  return Math.max(1, Math.floor(width / 390))
}

export function usePolyMasonry(containerRef) {
  const columnCount = ref(1)
  let ro = null

  function measure() {
    const el = containerRef.value
    if (el) columnCount.value = columnCountForWidth(el.clientWidth)
  }

  onMounted(() => {
    measure()
    if (typeof ResizeObserver !== 'undefined' && containerRef.value) {
      ro = new ResizeObserver(measure)
      ro.observe(containerRef.value)
    }
  })
  onUnmounted(() => ro && ro.disconnect())

  return { columnCount, distribute: distributeIntoColumns }
}
