/* eslint-disable no-nested-ternary */
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable no-unused-expressions */
/* eslint-disable prefer-destructuring */
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useRef, useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { IoIosArrowBack } from '@react-icons/all-files/io/IoIosArrowBack';
import { IoIosArrowForward } from '@react-icons/all-files/io/IoIosArrowForward';
import isSticky from '~hooks/stickyOnScroll';
import ScollX from '../../../../hooks/scroll-x';
import keygen from '~helpers/keygen';
import { anchorLink, removeSymbols } from '~helpers/strings';
import { translate } from '~helpers/getters';
import { Context } from '~context/MainProvider';
import styles from './anchor.module.scss';

function Anchor({
  module: { items },
  headerOffset = 80,
  isFixed = true,
  stickyOffset = 0,
  icon = null,
  showTitle = true,
  heightOfAnchor = 60,
  offset = 10,
  exclOperator = false,
  minCharactersForButtons = 86,
  setShowButtons = false,
  buttonScroll = 200,
  leftButtonIcon = <IoIosArrowBack />,
  rightButtonIcon = <IoIosArrowForward />,
}) {
  const [scrollX, setScrollX] = useState(0);
  const [scrollEnd, setScrollEnd] = useState(false);

  const itemsRef = useRef([]);
  const anchorContainerRef = useRef(null);
  const anchorListRef = useRef(null);
  const progressBar = useRef(null);
  const { translations } = useContext(Context) || {};
  let numberOfCharacters = 0;
  const anchorList = items.map((anchor) => {
    numberOfCharacters += anchor?.label?.length;
    return {
      id: `${anchor.label && removeSymbols(anchorLink(anchor?.label?.toLowerCase().trim()))}`,
      label: anchor.label,
      slug: `${anchor.label && anchorLink(anchor?.label?.toLowerCase().trim())}`,
    };
  });
  const showButtons = numberOfCharacters > minCharactersForButtons && setShowButtons;

  const updateButtons = (shift) => {
    setScrollEnd(
      Math.floor(anchorListRef.current.scrollWidth - (anchorListRef.current.scrollLeft + shift)) <=
        anchorListRef.current.offsetWidth
    );
  };

  const scroll = (shift) => {
    anchorListRef.current.scrollTo({
      left: anchorListRef.current.scrollLeft + shift,
      behavior: 'smooth',
    });
    updateButtons(shift);
    setScrollX(scrollX + shift);
  };

  function compact(array) {
    return array?.filter(Boolean);
  }

  const setActiveAnchor = () => {
    const { innerHeight, scrollY } = window;

    // Progress scroll bar
    const scrollHeight = document.querySelector('body').scrollHeight;
    const calcPercent = (scrollY * 100) / (scrollHeight - innerHeight);
    progressBar.current ? (progressBar.current.style.width = `${calcPercent}%`) : null;

    // Get element in viewport
    const currentAnchor = anchorList?.map((el) => {
      const element = document.getElementById(el.id);
      if (element?.offsetTop - headerOffset - heightOfAnchor - offset <= scrollY) {
        return element;
      }
      return null;
    });

    // Filter out undefined value
    const currentAnchorValues = compact(currentAnchor);
    const currentAnchorValuesLength = currentAnchorValues.length - 1;

    const activeElement = itemsRef.current.find(
      (element) =>
        element &&
        element.getAttribute('href') ===
          `#${currentAnchorValues[currentAnchorValuesLength]?.getAttribute('id')}`
    );

    // Remove all active classes
    itemsRef.current.forEach((li) => {
      li && li.parentNode.classList.remove(styles.active);
    });

    if (activeElement && anchorListRef.current) {
      activeElement.parentNode.classList.add(styles.active);

      const elementOffsetWidth = activeElement.offsetWidth;
      const elementOffsetLeft = activeElement.offsetLeft;

      if (elementOffsetLeft > anchorContainerRef.current.offsetWidth - elementOffsetWidth) {
        anchorListRef.current.scrollLeft =
          elementOffsetWidth + elementOffsetLeft + 5 - anchorContainerRef.current.offsetWidth;
      } else {
        anchorListRef.current.scrollLeft = 0;
      }
    } else if (anchorListRef.current) {
      // anchorListRef.current.scrollLeft = 0;
    }
  };

  const sticky = isFixed && isSticky(stickyOffset, setActiveAnchor, anchorContainerRef);

  const anchorItems = anchorList?.map((item, index) => (
    <li className={styles.anchorItem || ''}>
      <a
        className={`${styles.link || ''} anchor-carousel-gtm anchor-menu-gtm`}
        key={keygen()}
        draggable="false"
        // eslint-disable-next-line no-return-assign
        ref={(el) => (itemsRef.current[index] = el)}
        href={`#${item?.id && item.id}`}
      >
        {translate(translations, item.slug, item.label)}
        {icon}
      </a>
    </li>
  ));

  return (
    <div className={styles.containerAnchor || ''} ref={anchorContainerRef}>
      {showTitle && (
        <div className={`${styles.anchorTitle || ''}`}>
          <span>{translate(translations, 'anchor_title', 'Table of Contents')}</span>
        </div>
      )}

      <div
        className={`${sticky ? styles.stickyContainer || '' : styles.defaultConatiner || ''} 
                    ${exclOperator ? styles.usingExclOperator || '' : ''}`}
      >
        {showButtons && (
          <button
            className={`${styles.buttLeft} ${scrollX <= 0 ? styles.disabled : ''}`}
            onClick={() => scroll(-buttonScroll)}
            type="button"
          >
            {leftButtonIcon}
          </button>
        )}
        <ul ref={anchorListRef} className={`${styles.anchor || ''}`}>
          {anchorItems}
        </ul>
        {showButtons && (
          <button
            className={`${styles.buttRight} ${!scrollEnd ? '' : styles.disabled}`}
            onClick={() => scroll(buttonScroll)}
            type="button"
          >
            {rightButtonIcon}
          </button>
        )}
        {sticky && <div ref={progressBar} className={styles.progressBar || ''} />}
      </div>
    </div>
  );
}

Anchor.propTypes = {
  exclOperator: PropTypes.bool,
  module: PropTypes.shape({
    items: PropTypes.arrayOf(
      PropTypes.shape({
        label: PropTypes.string,
      })
    ),
  }).isRequired,
  headerOffset: PropTypes.number.isRequired,
  styles: PropTypes.shape({}),
  isFixed: PropTypes.bool,
  icon: PropTypes.element,
  showTitle: PropTypes.string,
  heightOfAnchor: PropTypes.number,
  offset: PropTypes.number,
  stickyOffset: PropTypes.number,
  buttonScroll: PropTypes.number,
  leftButtonIcon: PropTypes.shape({}),
  rightButtonIcon: PropTypes.shape({}),
  minCharactersForButtons: PropTypes.number,
  setShowButtons: PropTypes.bool,
};

export default Anchor;
