import { useCallback, useEffect } from "preact/hooks";

import useFit from "../utils/hooks/useFit";
import useI18n from "../utils/hooks/useI18n";
import useLnpLineInfo, { useLnpStopInfo } from "../utils/hooks/useLnp";
import useMapContext from "../utils/hooks/useMapContext";
import useRealtimeTrainByRouteIdentifier from "../utils/hooks/useRealtimeTrainsByRouteIdentifier";

/**
 * This component is responsible for updating the layout state in the context.
 */
function LayoutState() {
  const {
    details,
    embed,
    geolocation,
    hasDetails,
    hasLayerTree,
    hasLnp,
    hasNotification,
    hasPrint,
    hasRealtime,
    hasShare,
    isExportMenuOpen,
    isLayerTreeOpen,
    isSearchOpen,
    isShareMenuOpen,
    layertree,
    lineid,
    linesIds,
    lnp,
    mapset,
    notification,
    notificationid,
    notificationId,
    notificationlang,
    permalink,
    previewNotifications,
    print,
    realtime,
    search,
    selectedFeature,
    setFeaturesInfos,
    setHasDetails,
    setHasGeolocation,
    setHasLayerTree,
    setHasLnp,
    setHasMapset,
    setHasNotification,
    setHasPermalink,
    setHasPrint,
    setHasRealtime,
    setHasSearch,
    setHasShare,
    setHasStations,
    setHasToolbar,
    setIsEmbed,
    setIsExportMenuOpen,
    setIsLayerTreeOpen,
    setIsOverlayOpen,
    setIsSearchOpen,
    setIsShareMenuOpen,
    setLinesIds,
    setNotificationId,
    setNotificationSupportedLanguages,
    setStationId,
    setTrainId,
    share,
    stationId,
    stationid,
    tenant,
    toolbar,
    trainid,
    trainId,
  } = useMapContext();

  const lineInfo = useLnpLineInfo(lineid);
  const stopInfo = useLnpStopInfo(stationid);
  const trainInfo = useRealtimeTrainByRouteIdentifier(trainid);
  const fit = useFit();
  const { locale } = useI18n();

  // Define fallback languages from the notifications details
  useEffect(() => {
    const fallbackLangs =
      notificationlang
        ?.split(",")
        .map((lang) => {
          return lang.trim();
        })
        .filter((lang) => {
          return lang !== locale();
        }) || [];
    setNotificationSupportedLanguages(fallbackLangs);
  }, [notificationlang, setNotificationSupportedLanguages, locale]);

  useEffect(() => {
    setHasStations(!!tenant);
  }, [setHasStations, tenant]);

  useEffect(() => {
    setHasRealtime(realtime === "true");
  }, [realtime, setHasRealtime]);

  useEffect(() => {
    setHasNotification(notification === "true" || !!previewNotifications);
  }, [notification, previewNotifications, setHasNotification]);

  useEffect(() => {
    setHasMapset(mapset === "true");
  }, [mapset, setHasMapset]);

  useEffect(() => {
    setHasGeolocation(geolocation === "true");
  }, [geolocation, setHasGeolocation]);

  useEffect(() => {
    setHasPermalink(permalink === "true");
  }, [permalink, setHasPermalink]);

  useEffect(() => {
    setHasSearch(search === "true");
  }, [search, setHasSearch]);

  useEffect(() => {
    setIsEmbed(embed === "true");
  }, [embed, setIsEmbed]);

  useEffect(() => {
    setHasLnp(lnp === "true");
  }, [lnp, setHasLnp]);

  useEffect(() => {
    setHasShare(share === "true");
  }, [share, setHasShare]);

  useEffect(() => {
    setHasPrint(print === "true");
  }, [print, setHasPrint]);

  useEffect(() => {
    setHasDetails(details === "true");
  }, [details, setHasDetails]);

  useEffect(() => {
    setHasToolbar(toolbar === "true");
  }, [toolbar, setHasToolbar]);

  useEffect(() => {
    setHasLayerTree(layertree === "true");
  }, [layertree, setHasLayerTree]);

  useEffect(() => {
    setLinesIds(lineInfo?.external_id ? [lineInfo.external_id] : null);
  }, [lineInfo, setLinesIds]);

  // Zoom when linesids attribute changes
  useEffect(() => {
    fit.current(lineInfo, true);
  }, [lineInfo, fit]);

  useEffect(() => {
    setStationId(stopInfo?.external_id);
  }, [stopInfo, setStationId]);

  // Center and zoom when stationid attribute changes
  useEffect(() => {
    fit.current(stopInfo, true);
  }, [stopInfo, fit]);

  useEffect(() => {
    setNotificationId(notificationid);
  }, [notificationid, setNotificationId]);

  useEffect(() => {
    setTrainId(trainInfo?.train_id);
  }, [setTrainId, trainInfo]);

  // Center and zoom when trainid attribute changes
  useEffect(() => {
    fit.current(trainInfo, true);
  }, [trainInfo, fit]);

  // Close all menus
  const closeMenus = useCallback(() => {
    setIsLayerTreeOpen(false);
    setIsExportMenuOpen(false);
    setIsSearchOpen(false);
    setIsShareMenuOpen(false);
  }, [
    setIsExportMenuOpen,
    setIsLayerTreeOpen,
    setIsSearchOpen,
    setIsShareMenuOpen,
  ]);

  // Close all features details
  const closeFeatureDetails = useCallback(() => {
    setStationId(null);
    setTrainId(null);
    setNotificationId(null);
    setLinesIds(null);
    setFeaturesInfos(null);
  }, [
    setStationId,
    setTrainId,
    setNotificationId,
    setLinesIds,
    setFeaturesInfos,
  ]);

  useEffect(() => {
    if (isSearchOpen) {
      setIsLayerTreeOpen(false);
      setIsExportMenuOpen(false);
      setIsShareMenuOpen(false);
      setStationId(null);

      closeFeatureDetails();
    }
  }, [
    closeFeatureDetails,
    isSearchOpen,
    setIsExportMenuOpen,
    setIsLayerTreeOpen,
    setIsShareMenuOpen,
    setStationId,
  ]);

  useEffect(() => {
    if (isShareMenuOpen) {
      setIsLayerTreeOpen(false);
      setIsExportMenuOpen(false);
      setIsSearchOpen(false);

      closeFeatureDetails();
    }
  }, [
    isShareMenuOpen,
    closeFeatureDetails,
    setIsExportMenuOpen,
    setIsLayerTreeOpen,
    setIsSearchOpen,
  ]);

  useEffect(() => {
    if (isLayerTreeOpen) {
      setIsExportMenuOpen(false);
      setIsLayerTreeOpen(isLayerTreeOpen);
      setIsSearchOpen(false);
      setIsShareMenuOpen(false);

      closeFeatureDetails();
    }
  }, [
    isLayerTreeOpen,
    closeFeatureDetails,
    setIsExportMenuOpen,
    setIsLayerTreeOpen,
    setIsSearchOpen,
    setIsShareMenuOpen,
  ]);

  useEffect(() => {
    if (isExportMenuOpen) {
      setIsLayerTreeOpen(false);
      setIsExportMenuOpen(isExportMenuOpen);
      setIsSearchOpen(false);
      setIsShareMenuOpen(false);

      closeFeatureDetails();
    }
  }, [
    closeFeatureDetails,
    isExportMenuOpen,
    setIsExportMenuOpen,
    setIsLayerTreeOpen,
    setIsSearchOpen,
    setIsShareMenuOpen,
  ]);

  useEffect(() => {
    if (selectedFeature) {
      closeMenus();
      setTrainId(selectedFeature?.get("train_id") || null);
      setStationId(selectedFeature?.get("uid") || null);
      setNotificationId(selectedFeature?.get("situationId") || null);
    }
  }, [
    selectedFeature,
    closeMenus,
    setStationId,
    setTrainId,
    setNotificationId,
  ]);

  useEffect(() => {
    if (stationId) {
      closeMenus();

      setTrainId(null);
      setLinesIds(null);
      setNotificationId(null);
    }
  }, [closeMenus, setLinesIds, setNotificationId, setTrainId, stationId]);

  useEffect(() => {
    if (trainId) {
      closeMenus();

      // Close overlay details
      setStationId(null);
      setLinesIds(null);
      setNotificationId(null);
    }
  }, [closeMenus, setLinesIds, setNotificationId, setStationId, trainId]);

  useEffect(() => {
    if (notificationId) {
      closeMenus();

      // Close overlay details
      setStationId(null);
      setLinesIds(null);
      setTrainId(null);
    }
  }, [closeMenus, notificationId, setLinesIds, setStationId, setTrainId]);

  useEffect(() => {
    if (linesIds?.length) {
      closeMenus();

      // Close overlay details
      setStationId(null);
      setNotificationId(null);
      setTrainId(null);
    }
  }, [
    closeMenus,
    linesIds?.length,
    setNotificationId,
    setStationId,
    setTrainId,
  ]);

  useEffect(() => {
    setIsOverlayOpen(
      (hasPrint && isExportMenuOpen) ||
        (hasLayerTree && isLayerTreeOpen) ||
        (hasShare && isShareMenuOpen) ||
        (hasDetails && !!selectedFeature) || // For custom layers details.
        (hasDetails && hasRealtime && !!trainId) ||
        (hasDetails && tenant && !!stationId) ||
        (hasDetails && hasLnp && !!linesIds) ||
        (hasDetails && hasNotification && !!notificationId),
    );
  }, [
    hasDetails,
    selectedFeature,
    hasPrint,
    isExportMenuOpen,
    hasLayerTree,
    isLayerTreeOpen,
    hasShare,
    isShareMenuOpen,
    hasRealtime,
    trainId,
    tenant,
    stationId,
    setIsOverlayOpen,
    hasLnp,
    linesIds,
    hasNotification,
    notificationId,
  ]);

  return null;
}

export default LayoutState;
