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

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

import Image from "@enact/sandstone/Image";
import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";

import playImg from "../../../../../assets/images/btn/btn-play-thumb-nor.png";
import defaultImage from "../../../../../assets/images/img-thumb-empty-560.png";
import {
  finishVideoPreview,
  startVideoPlayer,
} from "../../../../actions/playActions";
import CustomImage from "../../../../components/CustomImage/CustomImage";
import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
import useScrollTo from "../../../../hooks/useScrollTo";
import { panel_names } from "../../../../utils/Config";
import { $L, scaleH, scaleW } from "../../../../utils/helperMethods";
import css from "./ThemeIndicator.module.less";
import ThemeIndicatorArrow from "./ThemeIndicatorArrow";

const Container = SpotlightContainerDecorator(
  { enterTo: "last-focused" },
  "div"
);
const SpottableComponent = Spottable("div");

const IMAGE_HEIGHT = scaleH(152);

function ThemeIndicator({
  selectedIndex,
  setSelectedIndex,
  themeProductInfos,
  themeProductInfo,
  thumbnailUrls,
  isSpotlight,
  soldoutFlag,
  launchedFromPlayer,
  isOnTop,
  isLoading,
}) {
  const dispatch = useDispatch();
  const [selectedImage, setSelectedImage] = useState(null);
  const [focused, setFocused] = useState(false);
  const [imageSelectedIndex, setImageSelectedIndex] = useState(0);
  const [autoPlaying, setAutoPlaying] = useState(
    !launchedFromPlayer && themeProductInfo?.prdtMediaUrl
  );
  const { cursorVisible } = useSelector((state) => state.common.appStatus);
  const panels = useSelector((state) => state.panels.panels);
  const imageLength = thumbnailUrls && thumbnailUrls.length;
  const topPanel = panels[panels.length - 1];
  const { getScrollTo, scrollTop } = useScrollTo();

  let imagePosition = IMAGE_HEIGHT * selectedIndex - IMAGE_HEIGHT;

  const canPlayVideo = useMemo(() => {
    return themeProductInfo?.prdtMediaUrl && imageSelectedIndex === 0;
  }, [themeProductInfo, imageSelectedIndex]);

  useEffect(() => {
    if (!launchedFromPlayer) {
      setAutoPlaying(themeProductInfo?.prdtMediaUrl);
    }
  }, [launchedFromPlayer, themeProductInfo?.prdtMediaUrl]);

  const getProductMediaUrlStatus = useMemo(() => {
    if (
      themeProductInfo?.prdtMediaUrl &&
      themeProductInfo?.prdtMediaUrl !== null
    ) {
      return true;
    }
    return false;
  }, [themeProductInfo]);

  useEffect(() => {
    if (thumbnailUrls) {
      if (getProductMediaUrlStatus) {
        const image = thumbnailUrls[imageSelectedIndex - 1];
        return setSelectedImage(image);
      } else {
        const image = thumbnailUrls[imageSelectedIndex];
        setSelectedImage(image);
      }
    }
  }, [thumbnailUrls, getProductMediaUrlStatus, imageSelectedIndex]);

  useEffect(() => {
    if (themeProductInfo?.prdtMediaUrl === null) {
      dispatch(finishVideoPreview());
    }
  }, [selectedIndex, themeProductInfo]);

  useEffect(() => {
    if (launchedFromPlayer && thumbnailUrls) {
      setSelectedImage(thumbnailUrls[0]);
    }
  }, [launchedFromPlayer, thumbnailUrls]);

  useEffect(() => {
    if (
      topPanel &&
      topPanel.name === panel_names.PLAYER_PANEL &&
      topPanel.panelInfo.modal === false
    ) {
      return; //prevent
    }

    if (!launchedFromPlayer && autoPlaying && themeProductInfo?.prdtMediaUrl) {
      //auto play.

      dispatch(
        startVideoPlayer({
          showUrl: themeProductInfo?.prdtMediaUrl,
          showNm: themeProductInfo?.prdtNm,
          patnrNm: themeProductInfo?.patncNm,
          patnrId: themeProductInfo?.patnrId,
          patncLogoPath: themeProductInfo?.patncLogoPath,
          orderPhnNo: themeProductInfo?.orderPhnNo,
          disclaimer: themeProductInfo?.disclaimer,
          subtitle: themeProductInfo?.prdtMediaSubtitlUrl,
          lgCatCd: themeProductInfo?.catCd,
          lgCatNm: themeProductInfo?.catNm,
          prdtId: themeProductInfo?.prdtId,
          patncNm: themeProductInfo?.patncNm,
          prdtNm: themeProductInfo?.prdtNm,
          thumbnailUrl: themeProductInfo?.thumbnailUrl960,
          shptmBanrTpNm: "MEDIA",
          modal: true,
          modalContainerId: "indicator_videoContainer", //to calc width, height, left, top
          modalClassName: modalClassNameChange(),
          spotlightDisable: true,
        })
      );
    }
  }, [
    dispatch,
    themeProductInfo,
    autoPlaying,
    focused,
    launchedFromPlayer,
    imageSelectedIndex,
  ]);

  const modalClassNameChange = useCallback(() => {
    if (imageSelectedIndex === 0) {
      if (focused) {
        return css.videoModal;
      }
      return "";
    } else {
      return css.videoModalHide;
    }
  }, [imageSelectedIndex, focused]);

  const videoContainerOnFocus = useCallback(() => {
    if (canPlayVideo) {
      setFocused(true);
    }
  }, [canPlayVideo]);

  const videoContainerOnBlur = useCallback(() => {
    if (canPlayVideo) {
      setFocused(false);
    }
  }, [canPlayVideo]);

  const handleUpClick = useCallback(() => {
    if (selectedIndex === 0) {
      return;
    }
    setSelectedIndex((prev) => prev - 1);
    setImageSelectedIndex(0);
    if (themeProductInfos.length - 1 !== selectedIndex) {
      scrollTop({ y: imagePosition - IMAGE_HEIGHT, animate: true });
    }
  }, [selectedIndex]);

  const handleDownClick = useCallback(() => {
    if (themeProductInfos.length - 1 === selectedIndex) {
      return;
    }

    setSelectedIndex((prev) => prev + 1);
    setImageSelectedIndex(0);
    if (selectedIndex > 1) {
      scrollTop({
        y: imagePosition,
        animate: true,
      });
    }
  }, [selectedIndex]);

  const renderItem = useCallback(
    ({ index, ...rest }) => {
      const { thumbnailUrl, imgUrls, hotelImgUrl } =
        themeProductInfos[index] || {};
      const imgUrl = imgUrls?.[0] || hotelImgUrl || thumbnailUrl || null;

      const handleItemClick = () => {
        setSelectedIndex(index);
        setImageSelectedIndex(0);
      };

      return (
        <>
          <SpottableComponent
            className={classNames(
              css.image,
              selectedIndex === index && css.selected,
              themeProductInfos[index]?.soldoutFlag === "Y" && css.selected
            )}
            onClick={handleItemClick}
            spotlightId={`indicator-image-${index}`}
            aria-label={
              index === 0
                ? "Selected, " + themeProductInfos[index].prdtNm + " " + "1"
                : themeProductInfos[index].prdtNm + " " + `${index + 1}`
            }
            {...rest}
          >
            <CustomImage
              src={imgUrl}
              alt=""
              fallbackSrc={defaultImage}
              className={classNames(css.smallImage)}
            />

            <span
              className={
                selectedIndex === index &&
                (themeProductInfos.length !== 1 || !soldoutFlag)
                  ? css.checkIcon
                  : undefined
              }
            />
            {(themeProductInfos.length === 1 && soldoutFlag) ||
              (selectedIndex !== index &&
                themeProductInfos[index]?.soldoutFlag === "Y" && (
                  <h3 className={css.soldoutLabel}>{$L("SOLD OUT")}</h3>
                ))}
          </SpottableComponent>
        </>
      );
    },
    [themeProductInfos, selectedIndex, soldoutFlag]
  );

  useEffect(() => {
    if (soldoutFlag) {
      Spotlight.focus("spotlightId_backBtn");
      return;
    }
    if (selectedIndex >= 3) {
      scrollTop({ y: IMAGE_HEIGHT * selectedIndex });
    }
    if (
      themeProductInfos &&
      themeProductInfos.length > 0 &&
      isSpotlight &&
      selectedIndex === 0
    ) {
      Spotlight.focus("indicatorGridlistContainer");
      Spotlight.focus("indicator-image-0");
    }

    if (selectedIndex > 0) {
      Spotlight.focus(`indicator-image-${selectedIndex}`);
    }
  }, [themeProductInfos, selectedIndex, isSpotlight, isLoading]);

  const handleVideoOnClick = useCallback(() => {
    if (canPlayVideo) {
      dispatch(
        startVideoPlayer({
          showUrl: themeProductInfo.prdtMediaUrl,
          showNm: themeProductInfo.prdtNm,
          patnrNm: themeProductInfo.patncNm,
          patncLogoPath: themeProductInfo.patncLogoPath,
          orderPhnNo: themeProductInfo.orderPhnNo,
          lgCatCd: themeProductInfo?.catCd,
          patnrId: themeProductInfo?.patnrId,
          lgCatNm: themeProductInfo?.catNm,
          prdtId: themeProductInfo?.prdtId,
          patncNm: themeProductInfo?.patncNm,
          prdtNm: themeProductInfo?.prdtNm,
          thumbnailUrl: themeProductInfo?.thumbnailUrl960,
          shptmBanrTpNm: "MEDIA",
          modal: false,
          modalContainerId: "indicator_videoContainer",
          modalClassName: css.videoModal,
          spotlightDisable: true,
        })
      );
      if (!autoPlaying && canPlayVideo) {
        setAutoPlaying(true);
      }
    }
  }, [canPlayVideo, autoPlaying]);

  const onSpotlightRight = useCallback((ev) => {
    Spotlight.focus("IndicatorGridlistContainer");
    ev.stopPropagation();
    ev.preventDefault();
  }, []);

  const onSpotlightLeft = useCallback(
    (ev) => {
      if (isOnTop) Spotlight.focus("spotlightId_backBtn");
      ev.stopPropagation();
      ev.preventDefault();
    },
    [isOnTop]
  );

  const renderThumbnail = useCallback(() => {
    return (
      <div className={css.thumbnailContainer}>
        <SpottableComponent
          spotlightId="indicator_videoContainer"
          disabled={!canPlayVideo}
          spotlightDisabled={!canPlayVideo}
          className={classNames(css.thumbnail)}
          onSpotlightRight={onSpotlightRight}
          onSpotlightLeft={onSpotlightLeft}
          onClick={handleVideoOnClick}
          onFocus={videoContainerOnFocus}
          onBlur={videoContainerOnBlur}
          aria-label={themeProductInfo?.prdtNm}
        >
          <CustomImage
            className={classNames(css.image)}
            src={selectedImage}
            fallbackSrc={autoPlaying && canPlayVideo ? "" : defaultImage}
            alt=""
          />
          {launchedFromPlayer && canPlayVideo && (
            <h3>
              <img src={playImg} alt="Play" />
            </h3>
          )}
        </SpottableComponent>

        {isOnTop && (
          <ThemeIndicatorArrow
            imageSelectedIndex={imageSelectedIndex}
            setImageSelectedIndex={setImageSelectedIndex}
            themeProductInfo={themeProductInfo}
            imageLength={imageLength}
          />
        )}
      </div>
    );
  }, [
    themeProductInfo,
    isOnTop,
    thumbnailUrls,
    imageSelectedIndex,
    selectedImage,
    autoPlaying,
    canPlayVideo,
    launchedFromPlayer,
  ]);

  return (
    <Container className={css.indicatorContainer}>
      <div>{renderThumbnail()}</div>
      <div>
        <SpottableComponent
          onClick={handleUpClick}
          spotlightDisabled={!cursorVisible}
          className={classNames(
            css.upButton,
            selectedIndex === 0 && css.disable
          )}
          aria-label="Move to up"
        />
        <Container
          className={css.tVirtualGridListContainer}
          spotlightId="IndicatorGridlistContainer"
        >
          {themeProductInfos && themeProductInfos.length > 0 && (
            <TVirtualGridList
              cbScrollTo={getScrollTo}
              className={css.tVirtualGridList}
              dataSize={themeProductInfos.length}
              itemWidth={144}
              itemHeight={144}
              spacing={8}
              renderItem={renderItem}
            />
          )}
        </Container>
        <SpottableComponent
          onClick={handleDownClick}
          spotlightDisabled={!cursorVisible}
          className={classNames(
            css.downButton,
            themeProductInfos.length - 1 === selectedIndex && css.disable
          )}
          aria-label="Move to down"
        />
      </div>
    </Container>
  );
}
const propsAreEqual = (prev, next) => {
  const keys = Object.keys(prev);
  const nextKeys = Object.keys(next);
  if (keys.length !== nextKeys.length) {
    return false;
  }
  for (let i = 0; i < keys.length; i++) {
    if (prev[keys[i]] !== next[keys[i]]) {
      if (JSON.stringify(prev[keys[i]]) === JSON.stringify(next[keys[i]])) {
        continue;
      }
      return false;
    }
  }
  return true;
};
export default React.memo(ThemeIndicator, propsAreEqual);
