import * as React from 'react';
import { isSameDate } from '@vkontakte/vkjs';
import { startOfTomorrow } from '../lib/date';
import { useDOM } from '../lib/dom';

/**
 * Опционально обновляемая дата сегодняшнего дня
 *
 * Дата - сегодня (в соответствии с системным временем)
 *
 * Часы, минуты, секунды, миллисекунды - произвольные
 *
 * @param listenDayChangesForUpdate - флаг по которому определяется, будет ли создаваться подписка на смену календарного дня
 */
export function useTodayDate(listenDayChangesForUpdate = false): Date {
  const { document, window } = useDOM();
  const [todayDate, setTodayDate] = React.useState(() => new Date());

  React.useEffect(
    function setupTodaysDateRecalculationListener() {
      if (!listenDayChangesForUpdate || !document || !window) {
        return;
      }

      let timeout: number | undefined = undefined;

      const recalcTimeout = () => {
        if (document.visibilityState === 'visible') {
          const now = new Date();

          const timeToDayChange = Number(startOfTomorrow()) - Number(now);

          // Удаляем старый таймаут
          window.clearTimeout(timeout);

          // Создаем новый таймаут
          timeout = window.setTimeout(() => {
            setTodayDate(new Date());
          }, timeToDayChange);

          // Если todayDate не обновился в таймаут - обновить при заходе на вкладку
          if (!isSameDate(todayDate, now)) {
            setTodayDate(now);
          }
        }
      };

      recalcTimeout();

      // Создаем слушатель visibilitychange, чтобы предотвратить пропуск обновления стейта после заморозки вкладки
      // Если человек ее долго не трогал или закрывал крышку ноута и тп
      // https://developer.chrome.com/blog/page-lifecycle-api/
      document.addEventListener('visibilitychange', recalcTimeout);

      return () => {
        window.clearTimeout(timeout);
        document.removeEventListener('visibilitychange', recalcTimeout);
      };
    },
    [document, listenDayChangesForUpdate, todayDate, window],
  );

  return todayDate;
}
