import { useMemo, useState, useEffect } from 'react';
import formats from './formats';
import ensureDate from './ensureDate';

/**
 * Hook to memoize a formatted local time that is SSR-safe. The hook accepts
 * a date-coerceable argument as well as a configuration object; it returns
 * a memoized set of formatted datetime strings. The hook also keeps track of
 * when the component calling it has been mounted on the client so that it can
 * initially format the datetime in a consistent timezone before localizing it
 * dynamically on the client. That prevents hydration errors caused by
 * mismatching time formats on the server and the client. If you specify
 * a `timeZone` in the configuration object then that timezone will be used
 * throughout the lifecycle of this hook.
 *
 * ```js
 *
 * import { useLocalTime } from '@politico/interactive-style';
 * ```
 *
 * @param {string|Date} time
 *   The date input to format as a localized time
 * @param {Object} options
 *   Options to dictate how the formatting behaves:
 *   - `timeZone`: a specific timezone in which to render the datetime
 *   - `truncateZeroMinutes`: whether to truncate minutes from time on the hour
 *   - `shortDate`: whether to use a short versino of the date
 */
const useLocalTime = function useLocalTime(time, options = {}) {
  const [isMounted, setIsMounted] = useState(false);
  useEffect(() => setIsMounted(true), []);
  const localTime = useMemo(() => {
    const timeAsDate = ensureDate(time);

    // Explicitly set timezone to East Coast until after client hydration
    const defaultTimeZone = isMounted ? undefined : 'America/New_York';
    const timeOptions = {
      timeZone: defaultTimeZone,
      ...options
    };
    if (!time) {
      return {
        day: null,
        time: null,
        timezone: null,
        weekday: null
      };
    }
    const dateData = {
      iso: timeAsDate.toISOString(),
      day: formats.day(timeAsDate, timeOptions),
      time: formats.time(timeAsDate, timeOptions),
      timezone: formats.timezone(timeAsDate, timeOptions),
      weekday: formats.weekday(timeAsDate, timeOptions),
      apdate: formats.apdate(timeAsDate, timeOptions)
    };
    const {
      timezone,
      time: timeFromDateData,
      apdate
    } = dateData;
    const apdatetime = `${apdate}, ${timeFromDateData} ${timezone}`;
    return {
      ...dateData,
      apdatetime,
      ap: apdatetime
    };
  }, [isMounted, time]);
  return localTime;
};
export default useLocalTime;