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';
//enact
import Skinnable from '@enact/sandstone/Skinnable';
import Spotlight from '@enact/spotlight';
import SpotlightContainerDecorator
  from '@enact/spotlight/SpotlightContainerDecorator';
import { Cancelable } from '@enact/ui/Cancelable';

//이미지
import shoptimeFullIcon
  from '../../../assets/icons/ic-lnb-logo-shoptime@3x.png';
import shopTimeIcon from '../../../assets/icons/ic-lnb-shoptime-symbol@3x.png';
import { resetPanels } from '../../actions/panelActions';
import { panel_names } from '../../utils/Config';
import CartIcon from './iconComponents/CartIcon';
import CategoryIcon from './iconComponents/CategoryIcon';
import FeaturedBrandIcon from './iconComponents/FeaturedBrandIcon';
import HomeIcon from './iconComponents/HomeIcon';
import HotPicksIcon from './iconComponents/HotPicksIcon';
import MyPageIcon from './iconComponents/MyPageIcon';
import OnSaleIcon from './iconComponents/OnSaleIcon';
import SearchIcon from './iconComponents/SearchIcon';
import TrendingNowIcon from './iconComponents/TrendingNowIcon';
import TabItem from './TabItem';
import TabItemSub from './TabItemSub';
import css from './TabLayout.module.less';

const Container = SpotlightContainerDecorator(
  { enterTo: "default-element" },
  "div"
);

const MainContainer = SpotlightContainerDecorator(
  { enterTo: "last-focused", continue5WayHold: true },
  "div"
);

const CancelableDiv = Cancelable(
  { modal: true, onCancel: "handleCancel" },
  Skinnable(Container)
);

class TabMenuItem {
  constructor(icons = "", title = "", id, path, target, children = []) {
    this.icons = icons;
    this.title = title;
    this.id = id;
    this.path = path;
    this.target = target;
    this.children = []; //TabMenuItem
    if (children && children.length > 0) {
      for (let i = 0; i < children.length; i++) {
        const tabmenu = new TabMenuItem(
          children[i].icons,
          children[i].title,
          children[i].id,
          children[i].path,
          children[i].target,
          children[i].children
        );
        this.children.push(tabmenu);
      }
    }
  }
  hasChildren = () => {
    return this.children.length > 0;
  };
  getChildren = () => {
    return this.children;
  };
}

const deActivateTabJabFunc = (func) => {
  func();
};
let deActivateTabJob = new Job(deActivateTabJabFunc, 2000);

const clearPanelSwitching = (ref) => {
  if (ref) {
    ref.current = false;
  }
};
let panelSwitchingJob = new Job(clearPanelSwitching, 500);

const COLLABSED_MAIN = 0;
const ACTIVATED_MAIN = 1;
const ACTIVATED_SUB = 2;
const EXTRA_AREA = 3;

const PANELS_HAS_TAB = [
  panel_names.CART_PANEL,
  panel_names.CATEGORY_PANEL,
  panel_names.FEATURED_BRANDS_PANEL,
  panel_names.HOME_PANEL,
  panel_names.HOT_PICKS_PANEL,
  panel_names.MY_PAGE_PANEL,
  panel_names.ON_SALE_PANEL,
  panel_names.SEARCH_PANEL,
  panel_names.TRENDING_NOW_PANEL,
];

export default function TabLayout({ topPanelName, onTabActivated }) {
  const dispatch = useDispatch();
  const [mainExpanded, setMainExpanded] = useState(false);
  const [mainSelectedIndex, setMainSelectedIndex] = useState(-1);
  const [secondDepthReduce, setSecondDepthReduce] = useState(false);
  const [tabs, setTabs] = useState([]);
  const [tabFocused, setTabFocused] = useState([false, false, false]); //COLLABSED_MAIN, ACTIVATED_MAIN, ACTIVATED_SUB
  const panelSwitching = useRef(null);
  const { cursorVisible } = useSelector((state) => state.common.appStatus);
  const data = useSelector((state) => state.home.menuData?.data);
  const panels = useSelector((state) => state.panels.panels);

  const menuItems = useMemo(() => {
    return [
      {
        icons: CategoryIcon,
        // target: [{ name: panel_names.CATEGORY_PANEL }],
      },
      {
        icons: MyPageIcon,
        // target: [{ name: panel_names.MY_PAGE_PANEL }],
      },
      {
        icons: SearchIcon,
        target: [{ name: panel_names.SEARCH_PANEL }],
      },
      {
        icons: HomeIcon,
        target: [{ name: panel_names.HOME_PANEL }],
      },
      {
        icons: FeaturedBrandIcon,
        // target: [{ name: panel_names.FEATURED_BRANDS_PANEL }],
      },
      {
        icons: OnSaleIcon,
        target: [{ name: panel_names.ON_SALE_PANEL }],
      },
      {
        icons: TrendingNowIcon,
        target: [{ name: panel_names.TRENDING_NOW_PANEL }],
      },
      {
        icons: HotPicksIcon,
        target: [{ name: panel_names.HOT_PICKS_PANEL }],
      },
      {
        icons: CartIcon,
        target: [{ name: panel_names.CART_PANEL }],
      },
    ];
  }, []);

  const getMenuData = (type) => {
    let result = [];

    switch (type) {
      case "Category":
        result = data?.homeCategory && data.homeCategory.map((item) => ({
          id: item.lgCatCd,
          title: item.lgCatNm,
          target: [
            {
              name: panel_names.CATEGORY_PANEL,
              panelInfo: {
                lgCatNm: item.lgCatNm,
                lgCatCd: item.lgCatCd,
                COUNT: item.COUNT,
              },
            },
          ],
        }));
        break;
      case "GNB":
        result = data?.gnb && data.gnb.map((item) => ({
          title: item.menuNm,
        }));
        break;

      case "Featured Brands":
        result = data?.shortFeaturedBrands && data.shortFeaturedBrands.map((item) => ({
          Id: item.patnrId,
          path: item.patncLogoPath,
          target: [
            {
              name: panel_names.FEATURED_BRANDS_PANEL,
              panelInfo: item.patnrId,
            },
          ],
        }));
        break;
      case "My Page":
        result = data?.mypage && data.mypage.map((item) => ({
          title: item.menuNm,
          target: [
            {
              name: panel_names.MY_PAGE_PANEL,
              panelInfo: item.menuOrd,
            },
          ],
        }));
        break;
    }
    //console.log("#data", data);
    return result;
  };

  const dataDivide = useCallback(() => {
    let keys = ["Category", "Featured Brands", "My Page"];

    if (data) {
      let mainTitle = getMenuData("GNB");

      mainTitle = mainTitle.sort((a, b) => {
        const order = {
          Category: 0,
          "My Page": 1,
          Search: 2,
          Home: 3,
          "Featured Brands": 4,
          "On sale": 5,
          "Trending Now": 6,
          "Hot Picks": 7,
          Cart: 8,
        };

        return order[a.title] - order[b.title];
      });

      for (let j = 0; j < keys.length; j++) {
        const currentKey = keys[j];
        const subData = getMenuData(currentKey);

        if (subData && subData.length > 0) {
          for (let i = 0; i < mainTitle.length; i++) {
            menuItems[i].title = mainTitle[i].title;
            if (mainTitle[i].title === currentKey) {
              menuItems[i].children = subData.map((subItem) => ({
                id: subItem.id,
                title: subItem.title,
                path: subItem.path,
                target: subItem.target,
              }));
            }
          }
        }
      }
    }
  }, [data, menuItems]);

  const makeTabmenu = useCallback(() => {
    const t = [];

    for (let i = 0; i < menuItems.length; i++) {
      const tabmenu = new TabMenuItem(
        menuItems[i].icons,
        menuItems[i].title,
        menuItems[i].id,
        menuItems[i].path,
        menuItems[i].target,
        menuItems[i].children
      );
      t.push(tabmenu);
    }

    return t;
  }, [data]);

  useEffect(() => {
    dataDivide();
    setTabs(makeTabmenu());
  }, [data]);

  const deActivateTab = useCallback(() => {
    setTabFocused([false, false, false, false]);
    setMainSelectedIndex(-1);
    setMainExpanded(false);
  }, []);

  const onTabHasFocus = useCallback(
    (type) => (event) => {
      switch (type) {
        case COLLABSED_MAIN:
        case ACTIVATED_MAIN: {
          if (!cursorVisible) {
            const parent = event.target.parentNode;
            const children = parent.childNodes;
            const index = Array.prototype.indexOf.call(children, event.target);
            setMainExpanded(true);
            setMainSelectedIndex(index - 1);
            setSecondDepthReduce(false);
          } else {
            if (!panelSwitching.current) {
              setMainExpanded(true);
            }
          }

          break;
        }
        case ACTIVATED_SUB: {
          if (cursorVisible) {
          }
          break;
        }
        case EXTRA_AREA: {
          if (cursorVisible) {
            return;
          }
        }
      }
      setTabFocused((prevState) => {
        const prev = [...prevState];
        prev[type] = true;
        return prev;
      });
    },
    [cursorVisible, deActivateTab]
  );

  const onTabBlur = useCallback(
    (type) => (event) => {
      switch (type) {
        case ACTIVATED_MAIN: {
          if (!cursorVisible) {
          }
          break;
        }
        case ACTIVATED_SUB: {
          if (!cursorVisible) {
          }
          break;
        }
        case EXTRA_AREA: {
          if (cursorVisible) {
            deActivateTabJob.stop();
            return;
          }
        }
      }
      setTabFocused((prevState) => {
        const prev = [...prevState];
        prev[type] = true;
        return prev;
      });
    },
    [cursorVisible]
  );

  const onFocus = (index) => {
    setMainSelectedIndex(index);

    if (showSubTab) {
      setSecondDepthReduce((prev) => !prev);
    }
  };

  const handleNavigation = useCallback(
    ({ index, target }) => {
      if (target && !showSubTab) {
        dispatch(resetPanels(target));
        deActivateTab();
        panelSwitching.current = true;
        panelSwitchingJob.start(panelSwitching);
      } else if (cursorVisible) {
        setMainExpanded(true);
      }
    },
    [cursorVisible, deActivateTab, dispatch]
  );

  const onClickSubItem = useCallback(
    ({ index, target }) => {
      if (target) {
        dispatch(resetPanels(target));

        deActivateTab();
        panelSwitching.current = true;
        panelSwitchingJob.start(panelSwitching);
      }
    },
    [dispatch, deActivateTab]
  );
  const onClickExtraArea = useCallback(
    ({ index, target }) => {
      deActivateTabJob.startAfter(100, deActivateTab);
    },
    [deActivateTab]
  );

  const tabActivated = useMemo(() => {
    return mainExpanded || mainSelectedIndex >= 0;
  }, [mainExpanded, mainSelectedIndex]);

  const showTab = useMemo(() => {
    if (!topPanelName || PANELS_HAS_TAB.indexOf(topPanelName) >= 0) {
      return true;
    }
    return false;
  }, [topPanelName]);

  const showSubTab = useMemo(() => {
    if (
      tabActivated &&
      tabs[mainSelectedIndex] &&
      tabs[mainSelectedIndex].hasChildren()
    ) {
      return true;
    }
    return false;
  }, [tabActivated, tabs, mainSelectedIndex]);

  const backKeyHandler = useCallback(
    (ev) => {
      if (tabActivated) {
        deActivateTab();
        ev.stopPropagation();
        ev.preventDefault();
        return true;
      }
    },
    [tabActivated, deActivateTab]
  );

  useEffect(() => {
    if (tabActivated) {
      setTimeout(() => {
        Spotlight.focus("activatedMain");
      }, 0);
    }
    if (onTabActivated) {
      onTabActivated(tabActivated && showTab);
    }
  }, [tabActivated, showTab]);

  useEffect(() => {
    setSecondDepthReduce(false);

    if (showSubTab) {
      tabs[mainSelectedIndex]?.children.map((item) => {
        if (item.path) {
          setSecondDepthReduce(true);
        }
      });
    }
  }, [secondDepthReduce, showSubTab]);

  if (!showTab) {
    return null;
  }
  return (
    <div className={classNames(css.tabLayoutWrap, !tabActivated && css.hide)}>
      {/* collabsed Main */}
      <Container
        className={classNames(css.tabWrap)}
        onFocus={onTabHasFocus(COLLABSED_MAIN)}
        onMouseOver={onTabHasFocus(COLLABSED_MAIN)}
        onBlur={onTabBlur(COLLABSED_MAIN)}
        onMouseLeave={onTabBlur(COLLABSED_MAIN)}
      >
        <h1 className={css.logo}>
          <img src={shopTimeIcon} alt="" />
        </h1>
        {tabs.map((item, index) => (
          <TabItem
            key={"tabitem" + index}
            expanded={false}
            selected={mainSelectedIndex === index}
            index={index}
            onClick={handleNavigation}
            icons={item.icons}
          />
        ))}
      </Container>
      {
        <CancelableDiv
          spotlightRestrict="self-only"
          spotlightId="activatedMain"
          className={classNames(
            css.expandedRootContainer,
            !tabActivated && css.hide
          )}
          handleCancel={backKeyHandler}
        >
          {/* expanded Main */}
          <MainContainer
            className={classNames(css.tabWrap, mainExpanded && css.expanded)}
            onFocus={onTabHasFocus(ACTIVATED_MAIN)}
            onMouseOver={onTabHasFocus(COLLABSED_MAIN)}
            onBlur={onTabBlur(ACTIVATED_MAIN)}
            onMouseLeave={onTabBlur(ACTIVATED_MAIN)}
          >
            <h1 className={css.logo}>
              <img
                src={mainExpanded ? shoptimeFullIcon : shopTimeIcon}
                alt=""
              />
            </h1>

            {tabActivated &&
              tabs.map((item, index) => (
                <TabItem
                  {...item}
                  onFocus={onFocus}
                  key={"tabitemExpanded" + index}
                  onClick={handleNavigation}
                  deActivateTab={deActivateTab}
                  showSubTab={showSubTab}
                  icons={item.icons}
                  expanded={mainExpanded}
                  mainSelected={
                    (panels.length === 0 && index === 0) ||
                    (Array.isArray(item.target) &&
                      item.target[0]?.name &&
                      panels[0]?.name === item.target[0]?.name)
                  }
                  selected={
                    (panels.length === 0 && index === 0) ||
                    (Array.isArray(item.children[0]?.target) &&
                      item.children[0]?.target[0]?.name &&
                      panels[0]?.name === item.children[0]?.target?.[0].name)
                  }
                  title={item.title}
                  index={index}
                  mainSelectedIndex={mainSelectedIndex}
                />
              ))}
          </MainContainer>
          {/* Sub */}
          {
            <Container
              spotlightId="activatedSub"
              className={classNames(
                css.tabWrap,
                css.secondDepthLayout,
                secondDepthReduce && css.secondDepthReduce,
                !showSubTab && css.hide
              )}
              onFocus={onTabHasFocus(ACTIVATED_SUB)}
              onMouseOver={onTabHasFocus(ACTIVATED_SUB)}
              onBlur={onTabBlur(ACTIVATED_SUB)}
              onMouseLeave={onTabBlur(ACTIVATED_SUB)}
            >
              {showSubTab &&
                tabs[mainSelectedIndex]?.children.map((item, index) => {
                  return (
                    <TabItemSub
                      {...item}
                      key={"tabitemSubmenu" + index}
                      onClick={onClickSubItem}
                      expanded={true}
                      index={index}
                      isSubItem={true}
                      deActivateTab={deActivateTab}
                      title={item.title}
                      lgCatCd={item.id}
                      path={item.path}
                      showSubTab={showSubTab}
                      selected={
                        Array.isArray(item.target) &&
                        item.target[0]?.panelInfo &&
                        panels[0]?.panelInfo === item.target[0]?.panelInfo
                      }
                    />
                  );
                })}
            </Container>
          }
          {/* Extra Area*/}
          {tabActivated && (
            <Container
              className={classNames(css.tabWrap, css.extraArea)}
              onClick={onClickExtraArea}
              onFocus={onTabHasFocus(EXTRA_AREA)}
              onMouseOver={onTabHasFocus(EXTRA_AREA)}
              onBlur={onTabBlur(EXTRA_AREA)}
              onMouseLeave={onTabBlur(EXTRA_AREA)}
            />
          )}
        </CancelableDiv>
      }
    </div>
  );
}
