import type { Dispatch, SetStateAction } from 'react' import { useMemo, useEffect, useState, useCallback, } from 'react' import { useQueryClient } from 'react-query' import throttle from 'lodash/throttle' import isEmpty from 'lodash/isEmpty' import includes from 'lodash/includes' import find from 'lodash/find' import isUndefined from 'lodash/isUndefined' import flatMapDepth from 'lodash/flatMapDepth' import uniqBy from 'lodash/uniqBy' import values from 'lodash/values' import size from 'lodash/size' import { querieKeys } from 'config' import type { DataItem, MatchScore, PlayerParam, } from 'requests' import { MatchInfo, PlayersStats, Player, getPlayersStats, getMatchParticipants, } from 'requests' import { getLocalStorageItem } from 'helpers/getLocalStorage' import { useObjectState, usePageParams } from 'hooks' import { StatsType, Tabs as StatsTabs } from 'features/MatchSidePlaylists/components/TabStats/config' import { getHalfTime } from 'features/MatchPage/helpers/getHalfTime' import { TOUR_COMPLETED_STORAGE_KEY } from 'features/MatchTour' import { Tabs } from 'features/MatchSidePlaylists/config' import { DISPLAYED_PARAMS_COLUMNS } from 'features/MatchSidePlaylists/components/PlayersTable/config' import { useFakeData } from './useFakeData' const REQUEST_DELAY = 5000 const STATS_POLL_INTERVAL = 30000 type UsePlayersStatsArgs = { matchProfile: MatchInfo, playingProgress: number, selectedStatsTable: StatsTabs, selectedTab: Tabs, setIsPlayersStatsFetching: Dispatch>, statsType: StatsType, } type PlayersData = { team1: Array, team2: Array, } export const usePlayersStats = ({ matchProfile, playingProgress, selectedStatsTable, selectedTab, setIsPlayersStatsFetching, statsType, }: UsePlayersStatsArgs) => { const [playersStats, setPlayersStats] = useObjectState>({}) const [playersData, setPlayersData] = useState({ team1: [], team2: [] }) const { profileId: matchId, sportName, sportType, } = usePageParams() const fakeData = useFakeData(matchProfile) const client = useQueryClient() const matchScore = client.getQueryData(querieKeys.matchScore) const isCurrentStats = statsType === StatsType.CURRENT_STATS const getParams = useCallback((stats: PlayersStats) => ( uniqBy(flatMapDepth(stats, values), 'id') as Array ), []) const fetchPlayers = useMemo(() => throttle(async (second?: number) => { const videoBounds = matchScore?.video_bounds || matchProfile?.video_bounds if ( !matchProfile?.team1.id || !matchProfile?.team2.id || !videoBounds ) return null try { return getMatchParticipants({ matchId, sportType, ...(!isUndefined(second) && getHalfTime(videoBounds, second)), }) } catch (e) { return Promise.reject(e) } }, REQUEST_DELAY), [ matchId, matchProfile?.team1.id, matchProfile?.team2.id, matchProfile?.video_bounds, matchScore?.video_bounds, sportType, ]) const fetchPlayersStats = useMemo(() => (async (team: 'team1' | 'team2', second?: number) => { const videoBounds = matchScore?.video_bounds || matchProfile?.video_bounds if (!sportName || !matchProfile?.[team].id || !videoBounds) return null try { return getPlayersStats({ matchId, sportName, teamId: matchProfile[team].id, ...(!isUndefined(second) && getHalfTime(videoBounds, second)), }) } catch (e) { return Promise.reject(e) } }), [ matchScore?.video_bounds, matchProfile, sportName, matchId, ]) const fetchData = useMemo(() => throttle(async (second?: number) => { const isTeam1Selected = selectedStatsTable === StatsTabs.TEAM1 if ( selectedTab !== Tabs.STATS || !includes([StatsTabs.TEAM1, StatsTabs.TEAM2], selectedStatsTable) || !matchProfile?.team1.id || !matchProfile?.team2.id || (!matchProfile?.live && !isCurrentStats && !isEmpty(playersStats[isTeam1Selected ? matchProfile.team1.id : matchProfile.team2.id])) ) return const [res1, res2] = await Promise.all([ fetchPlayers(second), isTeam1Selected ? fetchPlayersStats('team1', second) : fetchPlayersStats('team2', second), ]) as [Array | null, PlayersStats | null] const team1Players = find(res1, { team_id: matchProfile?.team1.id })?.players || [] const team2Players = find(res1, { team_id: matchProfile?.team2.id })?.players || [] const needUseFakeData = getLocalStorageItem(TOUR_COMPLETED_STORAGE_KEY) !== 'true' && ( isEmpty(team1Players) || isEmpty(res2) || size(getParams(res2)) <= DISPLAYED_PARAMS_COLUMNS ) setPlayersData({ team1: needUseFakeData ? fakeData.playersData[0].players : team1Players, team2: needUseFakeData ? fakeData.playersData[1].players : team2Players, }) setPlayersStats({ ...(isTeam1Selected && res2 && { [matchProfile.team1.id]: needUseFakeData ? fakeData.playersStats as unknown as PlayersStats : res2, }), ...(!isTeam1Selected && res2 && { [matchProfile.team2.id]: needUseFakeData ? fakeData.playersStats as unknown as PlayersStats : res2, }), }) setIsPlayersStatsFetching(false) // eslint-disable-next-line react-hooks/exhaustive-deps }, REQUEST_DELAY), [ fetchPlayers, fetchPlayersStats, setPlayersStats, matchProfile?.team1.id, matchProfile?.team2.id, matchProfile?.live, setIsPlayersStatsFetching, getParams, fakeData, selectedTab, selectedStatsTable, isCurrentStats, ]) const beforeCloseTourCallback = () => { isCurrentStats ? fetchData(playingProgress) : fetchData() } useEffect(() => { let interval: NodeJS.Timeout if (!isCurrentStats) { fetchData() } if (matchProfile?.live && !isCurrentStats) { interval = setInterval(() => { fetchData() }, STATS_POLL_INTERVAL) } return () => clearInterval(interval) }, [ fetchData, isCurrentStats, matchProfile?.live, ]) useEffect(() => { if (isCurrentStats) { fetchData(playingProgress) } }, [ fetchData, playingProgress, isCurrentStats, matchProfile?.live, ]) return { beforeCloseTourCallback, getParams, playersData, playersStats, } }