All files / web/src/arcade-games/know-your-world/hooks useRegionHint.ts

0% Statements 0/110
0% Branches 0/1
0% Functions 0/1
0% Lines 0/110

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111                                                                                                                                                                                                                             
import { useCallback, useMemo, useRef, useState } from 'react'
import { useLocale } from 'next-intl'
import { getHints, hasHints, type HintMap } from '../messages'
import type { Locale } from '@/i18n/messages'

/**
 * Hook to get hints for a region with cycling support.
 * Starts with a random hint, and can cycle to the next hint when user is struggling.
 *
 * Returns:
 * - currentHint: The current hint text (null if no hints)
 * - hintIndex: Current index (0-based)
 * - totalHints: Total number of hints available
 * - nextHint: Function to advance to the next hint (cycles)
 * - hasMoreHints: Whether there are hints the user hasn't seen yet
 */
export interface UseRegionHintResult {
  currentHint: string | null
  hintIndex: number
  totalHints: number
  nextHint: () => void
  hasMoreHints: boolean
}

export function useRegionHint(map: HintMap, regionId: string | null): UseRegionHintResult {
  const locale = useLocale() as Locale
  // Track which region we're showing hints for
  const lastRegionRef = useRef<string | null>(null)
  // Track the starting index (randomized on region change)
  const startIndexRef = useRef<number>(0)
  // Track how many hints we've cycled through for this region
  const [cycleOffset, setCycleOffset] = useState(0)

  // Get all hints for this region
  const allHints = useMemo(() => {
    if (!regionId) return []
    return getHints(locale, map, regionId) ?? []
  }, [locale, map, regionId])

  // Reset cycle offset when region changes
  if (regionId !== lastRegionRef.current) {
    lastRegionRef.current = regionId
    // Pick a random starting index for this region
    startIndexRef.current = allHints.length > 0 ? Math.floor(Math.random() * allHints.length) : 0
    // Reset cycle offset (can't call setState in render, so we check in useMemo below)
  }

  // Calculate current hint
  const result = useMemo(() => {
    // Reset cycle offset if region changed (detected by mismatch)
    const effectiveCycleOffset = regionId === lastRegionRef.current ? cycleOffset : 0

    if (allHints.length === 0) {
      return {
        currentHint: null,
        hintIndex: 0,
        totalHints: 0,
        hasMoreHints: false,
      }
    }

    const currentIndex = (startIndexRef.current + effectiveCycleOffset) % allHints.length
    return {
      currentHint: allHints[currentIndex],
      hintIndex: effectiveCycleOffset,
      totalHints: allHints.length,
      hasMoreHints: effectiveCycleOffset < allHints.length - 1,
    }
  }, [allHints, cycleOffset, regionId])

  // Reset cycle offset when region changes
  const prevRegionRef = useRef<string | null>(null)
  if (regionId !== prevRegionRef.current) {
    prevRegionRef.current = regionId
    if (cycleOffset !== 0) {
      setCycleOffset(0)
    }
  }

  // Function to advance to the next hint
  const nextHint = useCallback(() => {
    if (allHints.length > 1) {
      setCycleOffset((prev) => prev + 1)
    }
  }, [allHints.length])

  return {
    ...result,
    nextHint,
  }
}

// Legacy function signature for backwards compatibility
export function useRegionHintSimple(map: HintMap, regionId: string | null): string | null {
  const { currentHint } = useRegionHint(map, regionId)
  return currentHint
}

/**
 * Hook to check if hints exist for a region in the current locale
 */
export function useHasRegionHint(map: HintMap, regionId: string | null): boolean {
  const locale = useLocale() as Locale

  if (!regionId) {
    return false
  }

  return hasHints(locale, map, regionId)
}