import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";

import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux";

import { Job } from "@enact/core/util";
import { Panel } from "@enact/sandstone/Panels";
import Region from "@enact/sandstone/Region";
import Spotlight from "@enact/spotlight";
import Cancelable from "@enact/ui/Cancelable";

import LoadingPreloadImage from "../../../assets/images/intro/splash_02_stop.webp";
import LoadingAnimation from "../../../assets/images/intro/splash_03_end.webp";
import LoadingCompleteImage from "../../../assets/images/intro/splash_04_end.webp";
import LoadingShopOnTvImage from "../../../assets/images/intro/splash_end.jpg";
import { changeAppStatus, loadingComplete } from "../../actions/commonActions";
import CustomImage from "../../components/CustomImage/CustomImage";
import Loader from "../../components/Loader/Loader";
import PreloadImage from "../../components/PreloadImage/PreloadImage";
import TPopUp from "../../components/TPopUp/TPopUp";
import { $L } from "../../utils/helperMethods";
import css from "./LoadingPanel.module.less";
import useWhyDidYouUpdate from "../../hooks/useWhyDidYouUpdate";

const loadingImages = [LoadingPreloadImage, LoadingAnimation, LoadingCompleteImage];

const MIN_SHOWING_TIME = { launching: 4500, wait: 300, default: 1000 };
const MAX_SHOWING_TIME = 60000;
const MAX_SHOWING_TIME_UNLIMITED = 2147483647; // Number.MAX_SAFE_INTEGER;  MAX_SAFE_INTEGER 값 setTimeout 함수에서 미지원.
const DUMMY_DELAY = 1000;
const HIDING_TIME = 300;

const CancelablePanel = Cancelable({ modal: true, onCancel: "handleCancel" }, Panel);

let minShowingTimeJob, hidingJob, maxShowingTimeJob;

export default function LoadingPanel({ showLoadingPanel, ...rest }) {
  const { USE_STATE, USE_SELECTOR } = useWhyDidYouUpdate("LoadingPanel", {
    showLoadingPanel,
    ...rest,
  });
  const dispatch = useDispatch();
  const [showingStatus, setShowingStatus] = USE_STATE("showingStatus", {
    showing: true,
    hiding: false,
  });
  const [loadingType, setLoadingType] = USE_STATE("loadingType", "wait");
  const [readyToAni, setReadyToAni] = USE_STATE("readyToAni", false);
  const [readyToHide, setReadyToHide] = USE_STATE("readyToHide", false);

  const [loadingStep, setLoadingStep] = USE_STATE("loadingStep", 0);
  const [isVisible, setIsVisible] = USE_STATE("isVisible", false);
  const webOSVersion = USE_SELECTOR("webOSVersion", (state) => state.common.appStatus?.webOSVersion);

  const httpHeader = USE_SELECTOR("httpHeader", (state) => state.common.httpHeader);
  const deviceCountryCode = httpHeader?.["X-Device-Country"] || "";

  const resumeSpotlightTimeoutRef = useRef(null);
  const containerRef = useRef(null);

  useEffect(() => {
    if (showLoadingPanel.show) {
      const handleKeyDown = (e) => {
        e.stopPropagation();
        e.preventDefault();
      };

      window.addEventListener("keydown", handleKeyDown, true);
      return () => {
        window.removeEventListener("keydown", handleKeyDown, true);
      };
    }
  }, [showLoadingPanel]);

  useEffect(() => {
    return () => {
      if (minShowingTimeJob) minShowingTimeJob.stop();
      if (hidingJob) hidingJob.stop();
      if (maxShowingTimeJob) maxShowingTimeJob.stop();
    };
  }, []);

  useEffect(() => {
    if (readyToHide && !showLoadingPanel.show) {
      setTimeout(() => {
        setShowingStatus({ showing: false, hiding: true });
      }, DUMMY_DELAY);
    }
  }, [readyToHide, showLoadingPanel]);

  useEffect(() => {
    if (!showingStatus.showing && !showingStatus.hiding) {
      Spotlight.resume();
    }
  }, [showingStatus]);

  useEffect(() => {
    if (!showingStatus.showing) {
      if (showingStatus.hiding) {
        if (!hidingJob) {
          hidingJob = new Job(() => {
            setShowingStatus({ showing: false, hiding: false });
          }, HIDING_TIME);
        }
        hidingJob.start();
      } else {
        setReadyToHide(false);
        setReadyToAni(false);

        minShowingTimeJob && minShowingTimeJob.stop();
        hidingJob && hidingJob.stop();
        maxShowingTimeJob && maxShowingTimeJob.stop();
        maxShowingTimeJob = null;
        dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
      }
    }
  }, [showingStatus]);

  useEffect(() => {
    if (showLoadingPanel.show) {
      Spotlight.pause();
    } else if (readyToHide && readyToAni) {
      resumeSpotlightTimeoutRef.current = setTimeout(() => {
        if (!showLoadingPanel.show && readyToHide && readyToAni) {
          dispatch(loadingComplete(true));
          setShowingStatus({ showing: false, hiding: true });
        }
      }, HIDING_TIME);
    }

    return () => {
      if (resumeSpotlightTimeoutRef.current) {
        clearTimeout(resumeSpotlightTimeoutRef.current);
      }
    };
  }, [showLoadingPanel.show, readyToHide, readyToAni, dispatch]);

  useEffect(() => {
    if (showLoadingPanel.show) {
      if (!maxShowingTimeJob) {
        maxShowingTimeJob = new Job(() => {
          setShowingStatus({ showing: false, hiding: true });
        });
      }
      maxShowingTimeJob.startAfter(showLoadingPanel.type === "wait" ? MAX_SHOWING_TIME_UNLIMITED : MAX_SHOWING_TIME);

      setShowingStatus({ showing: true, hiding: false });
      setLoadingType(showLoadingPanel.type);
      if (showLoadingPanel.type === "wait") {
        setIsVisible(true);
      }
    }
  }, [showLoadingPanel]);

  const handleCancel = useCallback((e) => {
    if (e) e.stopPropagation();
  }, []);

  const onPreImageLoadComplete = useCallback(() => {
    setReadyToAni(true);

    if (minShowingTimeJob) {
      minShowingTimeJob.stop();
    }

    let minTime = MIN_SHOWING_TIME[loadingType];

    if (!minTime) {
      minTime = MIN_SHOWING_TIME.default;
    }

    minShowingTimeJob = new Job(() => {
      setReadyToHide(true);
    }, minTime);

    if (showingStatus.showing) {
      minShowingTimeJob.start();
    }
  }, [showingStatus, loadingType]);

  const handleLoad = () => {
    setIsVisible(true); // 이미지가 로드되면 visible 상태를 true로 설정
  };

  useEffect(() => {
    if (containerRef.current) {
      containerRef.current.classList.add(css.visible);
    }
  }, [loadingStep]);

  useEffect(() => {
    let timer;
    if (isVisible) {
      if (loadingStep < 1) {
        timer = setTimeout(() => {
          setIsVisible(false); // 다음 이미지를 로드하기 전에 숨김
          setLoadingStep((prevStep) => prevStep + 1);
        }, 1000);
      } else {
        return;
      }
    }
    return () => clearTimeout(timer);
  }, [isVisible, loadingStep]);

  const renderImages = useCallback(() => {
    switch (loadingType) {
      case "launching": {
        const fontMap = [
          css.smart300,
          css.smart400,
          css.smart500,
          css.smart600,
          css.smart700,
          css.arial,
          css.arialBold,
          css.arialBlack,
        ];
        return (
          <>
            {deviceCountryCode === "RU" ? ( // RU loading image
              <img
                className={css.fullPageImageShopOnTv}
                src={LoadingShopOnTvImage}
                onLoad={handleLoad}
                alt="Loading Image"
              />
            ) : webOSVersion && Number(webOSVersion) < 5 ? ( // webOs5.0 미만 loading image
              <img className={css.fullpageImage} src={LoadingCompleteImage} onLoad={handleLoad} alt="Loading Image" />
            ) : (
              loadingStep < 2 && ( // normal loading image
                <img
                  className={css.fullpageImage}
                  src={loadingImages[loadingStep]}
                  onLoad={handleLoad}
                  alt="Loading Image"
                />
              )
            )}
            {fontMap.map((layout, index) => (
              <div key={"font" + index} className={classNames(css.fontLoading, layout)}>
                fontLoading
              </div>
            ))}
          </>
        );
      }
      case "wait":
        return <Loader />;

      default:
        return null;
    }
  }, [loadingType, loadingStep, deviceCountryCode, webOSVersion]);

  const hidingStyle = showingStatus.hiding ? { transition: "opacity " + HIDING_TIME + "ms ease", opacity: 0 } : {};

  if (showingStatus.showing || showingStatus.hiding) {
    return (
      <Region title={"LG Shoptime logo"} aria-label="LG Shoptime logo">
        <CancelablePanel {...rest} className={css.panel} style={hidingStyle} handleCancel={handleCancel}>
          <PreloadImage preloadImages={loadingImages} onLoadComplete={onPreImageLoadComplete} />
          {readyToAni && (
            <div
              className={classNames(
                css.container,
                loadingType === "launching" ? css.launchingWrap : null,
                isVisible && css.visible
              )}
              ref={containerRef}
            >
              {renderImages()}
            </div>
          )}
        </CancelablePanel>
        {/* <TPopUp
          kind="loadingPopup"
          open
          hasButton
          button1Text={$L("Yes")}
          button2Text={$L("No")}
          hasText
          title={$L("Exit Shop Time")}
          text={$L(
            "If you have Changed your LG service country setting, the usage information in Shop Time during your previous country setting will be deleted. Do you want to proceed?"
          )}
        /> */}
        {/* <TPopUp
          kind="loadingPopup"
          open
          hasButton
          button1Text={$L("EXIT")}
          hasText
          title={$L("Exit Shop Time")}
          text={$L("This is an unsupported country")}
        /> */}
      </Region>
    );
  } else {
    return null;
  }
}

/* ---------- 

- TODO

1. 런칭 로딩 제외한 나머지 로딩 분기 처리 필요

---------- */
