import {useCallback, useEffect, useMemo, useState} from 'react'; import DevicesRepositoryImpl from '../repositories/DevicesRepositoryImpl'; import DevicesAPI from '../api/clients/DevicesAPI'; import AuthRepositoryImpl from '../repositories/AuthRepositoryImpl'; import AuthAPI from '../api/clients/AuthAPI'; import LineDetail from '../../domain/repositories/LineDetail'; import {Line} from '../../presentation/screens/BusStopInfoScreen'; import BusStopInfoService from '../../domain/services/BusStopInfoService'; export enum Status { LOADING = 'LOADING', SUCCESS = 'SUCCESS', ERROR = 'ERROR', } interface State { status: Status; lines: LineDetail[]; displayedLines: Line[]; currentIndex: number; stopMessage: string; stopName: string; } const DEVICE_ID = 'TTM543870hyt'; const BASE_URL = 'https://transporte.hz.kursor.cl'; const USER = 'usuario1'; const PASSWORD = 'usuario1'; const useDevices = () => { const [state, setState] = useState({ status: Status.LOADING, currentIndex: 0, stopMessage: '', displayedLines: [], lines: [], stopName: 'Sin información - Sin información', }); const baseUrl = BASE_URL; // TODO: remoteconfig ? const username = USER; const password = PASSWORD; const deviceApi = useMemo(() => new DevicesAPI(baseUrl), [baseUrl]); const authApi = useMemo(() => new AuthAPI(baseUrl), [baseUrl]); const devicesRepository = useMemo( () => new DevicesRepositoryImpl(deviceApi), [deviceApi], ); const authRepository = useMemo( () => new AuthRepositoryImpl(authApi), [authApi], ); const setDisplayedLines = useCallback( (lineDetails: LineDetail[], stopMessage: string, stopName: string) => { if (!lineDetails || !stopName) { return; } try { let busStopInfoService = new BusStopInfoService(lineDetails); const linesWithArrivals = lineDetails .map(line => { try { busStopInfoService.getNextArraival(line.lineNumber); return line; } catch (error) { return undefined; } }) .filter((line): line is LineDetail => line !== undefined); busStopInfoService = new BusStopInfoService(linesWithArrivals); const linesToDisplay: Line[] = busStopInfoService .pruneBusList(state.currentIndex, 21) // result 7 * 3 .map(line => { try { const nextArraival = busStopInfoService.getNextArraival( line.lineNumber, ); const estimatedArrivalTimeInMinutes = busStopInfoService.checkArraivalTime(nextArraival); const lineLetter = busStopInfoService.getLineLetterFromDescription( line.description, ); const lineNumber = busStopInfoService.getLineNumberFromDescription( line.description, ); const lineDescription = busStopInfoService.getLineDescription( line.description, line.lineNumber, ); return { backgroundColor: line.backgroundColor, estimatedArrivalTimeInMinutes, letterColor: line.letterColor, lineLetter, lineNumber, lineDescription, }; } catch (error) { return undefined; } }) .filter((line): line is Line => line !== undefined); setState(prevState => { const displayedLines = linesToDisplay.length === 0 ? prevState.displayedLines : linesToDisplay; return { ...prevState, displayedLines, stopMessage, stopName, lines: lineDetails, }; }); } catch (error: unknown) { setState(prevState => ({ ...prevState, status: Status.ERROR, })); } }, [state.currentIndex], ); useEffect(() => { const init = async () => { try { const token = await authRepository.auth({username, password}); const {lineDetails, stopMessage} = await devicesRepository.getDeviceInfo({ deviceId: DEVICE_ID, token, }); const {stopName} = await devicesRepository.whoAmI({ deviceId: DEVICE_ID, token, }); if (!lineDetails) { setState((prevState: State) => ({ ...prevState, status: Status.ERROR, })); return; } setState((prevState: State) => ({ ...prevState, ...{ lines: lineDetails, stopMessage, stopName, status: Status.SUCCESS, }, })); } catch (error) { setState((prevState: State) => ({ ...prevState, status: Status.ERROR, })); } }; init(); }, [authRepository, devicesRepository, password, username]); useEffect(() => { setDisplayedLines(state.lines, state.stopMessage, state.stopName); }, [setDisplayedLines, state.lines, state.stopMessage, state.stopName]); useEffect(() => { const interval = setInterval(() => { setState(prevState => { const isGreatherThanLinesLength = (prevState.currentIndex || 1) + 21 >= state.lines.length; return { ...prevState, currentIndex: isGreatherThanLinesLength ? 0 : (prevState.currentIndex || 1 + 21) % state.lines.length, }; }); }, 5000); return () => { clearInterval(interval); }; }, [state.lines, state.status]); return {state}; }; export default useDevices;