import { useState, useEffect, useRef, useCallback } from 'react' import { addDays, subDays } from 'date-fns' import { useMap } from '@/app/map-context' import { useSubscription, gql } from '@apollo/client' import { parse } from 'date-fns' import { UTCDate } from "@date-fns/utc"; import { toZonedTime } from 'date-fns-tz'; const speedIntervals = { slow: 2000, normal: 1000, fast: 500 } interface UseTimelineOptions { startDate?: Date endDate?: Date initialDate?: Date onDateChange?: (date: Date) => void autoPlay?: boolean autoUpdate?: boolean } enum WsStatus { CONNECTING = 'connecting', CONNECTED = 'connected', DISCONNECTED = 'disconnected' } export function useTimeline({ startDate = subDays(new Date(), 30), endDate = new Date(), onDateChange, autoPlay = false }: UseTimelineOptions = {}) { const [isPlaying, setIsPlaying] = useState(autoPlay) const [speed, setSpeed] = useState<'slow' | 'normal' | 'fast'>('normal') const intervalRef = useRef(null) const { setTime, currentDatetime, setTimelineTime, timelineDatetime } = useMap() const [wsStatus, setWsStatus] = useState(WsStatus.DISCONNECTED) const updateDate = useCallback((newDate: Date) => { setTime(newDate) onDateChange?.(newDate) }, [onDateChange]) const play = useCallback(() => { setIsPlaying(true) }, []) const pause = useCallback(() => { setIsPlaying(false) }, []) const togglePlay = useCallback(() => { setIsPlaying(prev => !prev) }, []) const skipForward = useCallback(() => { if (!currentDatetime) return; const newDate = addDays(currentDatetime, 1) if (newDate <= endDate) { updateDate(newDate) } }, [currentDatetime, endDate, updateDate]) const skipBackward = useCallback(() => { if (!currentDatetime) return; const newDate = subDays(currentDatetime, 1) if (newDate >= startDate) { updateDate(newDate) } }, [currentDatetime, startDate, updateDate]) const changeSpeed = useCallback((newSpeed: 'slow' | 'normal' | 'fast') => { setSpeed(newSpeed) }, []) const jumpToDate = useCallback((date: Date) => { if (date >= startDate && date <= endDate) { updateDate(date) } }, [startDate, endDate, updateDate]) // 自动播放逻辑 useEffect(() => { if (isPlaying) { intervalRef.current = setInterval(() => { if (!currentDatetime) return; const nextDate = addDays(currentDatetime, 1) if (nextDate <= endDate) { updateDate(nextDate) } else { // 到达结束日期,停止播放 setIsPlaying(false) } }, speedIntervals[speed]) } else { if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } } return () => { if (intervalRef.current) { clearInterval(intervalRef.current) } } }, [isPlaying, currentDatetime, endDate, speed, updateDate]) // 清理定时器 useEffect(() => { return () => { if (intervalRef.current) { clearInterval(intervalRef.current) } } }, []) return { timelineDatetime, setTimelineTime, currentDatetime, isPlaying, speed, startDate, endDate, play, pause, togglePlay, skipForward, skipBackward, changeSpeed, jumpToDate, updateDate, setTime, wsStatus, setWsStatus } }