<script setup lang="ts">
import { computed, onMounted, onBeforeUnmount, ref } from 'vue'

const props = withDefaults(
  defineProps<{
    vertical?: boolean
    label?: string
    height?: number
    size?: number
  }>(),
  {
    vertical: false,
    height: 14,
    size: 18,
  },
)

// 16-leaf radial wreath, used as the vertical divider's center ornament
const radialLeaves = Array.from({ length: 16 }, (_, i) => {
  const angle = i * 22.5
  const isB = i % 2 === 1
  return isB
    ? {
        path: 'M340,72 C350,80 352,97 343,113 C339,108 332,94 335,77 Z',
        line: { x1: 340, y1: 75, x2: 343, y2: 111 },
        transform: `rotate(${angle},340,180)`,
      }
    : {
        path: 'M340,70 C350,78 352,96 343,112 C339,107 332,93 335,76 Z',
        line: { x1: 340, y1: 73, x2: 343, y2: 110 },
        transform: `rotate(${angle},340,180)`,
      }
})

// Running laurel: the loader's Type-A leaf rotated 90° CW and tiled, fitting
// only whole leaves across the container width (no clipped edge leaves).
const wrapRef = ref<HTMLElement | null>(null)
const uid = `ld${Math.random().toString(36).slice(2, 8)}`
const svgW = ref(800)
let ro: ResizeObserver | null = null

onMounted(() => {
  if (!wrapRef.value) return
  svgW.value = Math.floor(wrapRef.value.getBoundingClientRect().width)
  if (typeof ResizeObserver === 'undefined') return
  ro = new ResizeObserver(([entry]) => {
    if (entry) svgW.value = Math.floor(entry.contentRect.width)
  })
  ro.observe(wrapRef.value)
})

onBeforeUnmount(() => {
  ro?.disconnect()
})

const h = computed(() => props.height)
const k = computed(() => (h.value * 0.7) / 20)
const tileW = computed(() => Math.round(42 * k.value))
const cx = computed(() => tileW.value / 2)
const cy = computed(() => h.value * 0.55)

const tf = (x: number, y: number): [number, number] => [
  cx.value + (y - 91) * k.value,
  cy.value - (x - 340) * k.value,
]

const rawPts: Array<[number, number]> = [
  [340, 70],
  [350, 78],
  [352, 96],
  [343, 112],
  [339, 107],
  [332, 93],
  [335, 76],
]
const f = (n: number) => n.toFixed(1)

const pts = computed(() => rawPts.map(([x, y]) => tf(x, y)))

const leafPath = computed(() => {
  const p = pts.value
  return [
    `M${f(p[0]![0])} ${f(p[0]![1])}`,
    `C${f(p[1]![0])} ${f(p[1]![1])} ${f(p[2]![0])} ${f(p[2]![1])} ${f(p[3]![0])} ${f(p[3]![1])}`,
    `C${f(p[4]![0])} ${f(p[4]![1])} ${f(p[5]![0])} ${f(p[5]![1])} ${f(p[6]![0])} ${f(p[6]![1])}`,
    'Z',
  ].join(' ')
})

const numTiles = computed(() => Math.max(1, Math.floor(svgW.value / tileW.value)))
const usedW = computed(() => numTiles.value * tileW.value)
const offsetX = computed(() => (svgW.value - usedW.value) / 2)
</script>

<template>
  <div v-if="vertical" class="nych-divider--vertical" role="separator">
    <svg
      viewBox="226 66 228 228"
      :width="size"
      :height="size"
      fill="currentColor"
      stroke="currentColor"
      aria-hidden="true"
      style="flex-shrink: 0"
    >
      <g v-for="(leaf, i) in radialLeaves" :key="i" :transform="leaf.transform">
        <path :d="leaf.path" />
        <line
          :x1="leaf.line.x1"
          :y1="leaf.line.y1"
          :x2="leaf.line.x2"
          :y2="leaf.line.y2"
          stroke-width="0.8"
          stroke-linecap="round"
        />
      </g>
    </svg>
  </div>
  <div v-else class="nych-divider" role="separator" :data-p="label ? 'label' : undefined">
    <span v-if="label" class="nych-divider-label">{{ label }}</span>
    <div v-else ref="wrapRef" style="width: 100%; height: 100%">
      <svg :width="svgW" :height="h" aria-hidden="true">
        <defs>
          <pattern
            :id="uid"
            :x="offsetX"
            y="0"
            :width="tileW"
            :height="h"
            patternUnits="userSpaceOnUse"
          >
            <path :d="leafPath" fill="currentColor" opacity="0.85" />
            <line
              :x1="f(pts[0]![0])"
              :y1="f(pts[0]![1])"
              :x2="f(pts[3]![0])"
              :y2="f(pts[3]![1])"
              stroke="currentColor"
              stroke-width="0.5"
              stroke-linecap="round"
              opacity="0.4"
            />
          </pattern>
          <clipPath :id="`${uid}c`">
            <rect :x="offsetX" y="0" :width="usedW" :height="h" />
          </clipPath>
        </defs>
        <rect :width="svgW" :height="h" :fill="`url(#${uid})`" :clip-path="`url(#${uid}c)`" />
      </svg>
    </div>
  </div>
</template>
