/**
 * Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
 */
import React, {useEffect, useRef, useState, ReactNode} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {IconDefinition, IconProp} from '@fortawesome/fontawesome-svg-core';

import {useComponentVisible, useCurrentWidth} from 'utility/custom-hooks';
import {IconMenuWrapper, IconMenuDropDownWrapper, IconMenuContent, IconMenuPointer, DropdownIcon, IconMenuDropDownItem} from './style';
import {IconMenuPosition, defaultArrowWidth, defaultArrowEdgeGap} from './types';

interface IIconMenuItems {
  title: string;
  value: string;
  className?: string;
  onSelect?: () => void;
  onClick?: () => void;
  modal?: {
    component: ReactNode;
    action?: () => void;
  };
}

interface IMenuPointerStyle {
  left?: number | string;
  right?: number | string;
  top?: number | string;
  bottom?: number | string;
  width?: number | string;
  height?: number | string;
}

interface IIconMenu {
  items: IIconMenuItems[];
  icon?: IconDefinition | IconProp;
  iconClassName?: string;
  iconColor?: string;
  title?: string;
  menuVisible?: boolean;
  showTail?: boolean;
  position?: IconMenuPosition;
  hasPointer?: boolean;
  dropdownMargin?: number;
  margin?: number | string;
  disabled?: boolean;
}

const IconMenu = ({
  items = [],
  icon,
  iconClassName,
  iconColor = 'white',
  menuVisible = false,
  title,
  showTail = true,
  position = IconMenuPosition.BottomLeft,
  hasPointer = true,
  dropdownMargin = 0,
  margin,
  disabled
}: IIconMenu): React.JSX.Element => {
  const dropdownRef = useRef<HTMLDivElement>(null);
  const [dropdownStyle, setDropdownStyle] = useState<any>(null);
  const [menuPointerStyle, setMenuPointerStyle] = useState<IMenuPointerStyle>({
    right: -defaultArrowWidth / 2,
    top: '50%'
  });
  const {ref, isComponentVisible, setIsComponentVisible} = useComponentVisible(menuVisible);
  const width = useCurrentWidth();

  useEffect(() => {
    if (!isComponentVisible) {
      setDropdownStyle(null);
    }
  }, [isComponentVisible]);

  useEffect(() => {
    if (ref.current && dropdownRef.current && isComponentVisible && position) {
      const refRect = (ref.current as HTMLElement).getBoundingClientRect();
      const dropdownRefRect = (dropdownRef.current as HTMLElement).getBoundingClientRect();
      const newArrowPosition: IMenuPointerStyle = {
        width: `${defaultArrowWidth}px`,
        height: `${defaultArrowWidth}px`
      };
      const pointerMargin = Math.sqrt((defaultArrowWidth * defaultArrowWidth) / 2);
      let top = 0;
      let left = 0;

      switch (position) {
        case IconMenuPosition.Right: {
          newArrowPosition.top = `calc(50% - ${defaultArrowWidth / 2}px)`;
          newArrowPosition.left = `-${defaultArrowWidth / 2}px`;
          top = refRect.top + refRect.height / 2 - dropdownRefRect.height / 2;
          left = refRect.left + refRect.width + pointerMargin + dropdownMargin;

          break;
        }

        case IconMenuPosition.Top: {
          newArrowPosition.left = '50%';
          newArrowPosition.bottom = `-${defaultArrowWidth / 2}px`;
          top = refRect.top - dropdownRefRect.height - pointerMargin - dropdownMargin;
          left = refRect.left + refRect.width / 2 - dropdownRefRect.width / 2;

          break;
        }

        case IconMenuPosition.TopLeft: {
          newArrowPosition.right = `${defaultArrowEdgeGap}px`;
          newArrowPosition.bottom = `-${defaultArrowWidth / 2}px`;
          top = refRect.top - dropdownRefRect.height - pointerMargin - dropdownMargin;
          left = refRect.left + refRect.width / 2 - dropdownRefRect.width + defaultArrowWidth / 2 + defaultArrowEdgeGap;

          break;
        }

        case IconMenuPosition.TopRight: {
          newArrowPosition.left = `${defaultArrowEdgeGap}px`;
          newArrowPosition.bottom = `-${defaultArrowWidth / 2}px`;
          top = refRect.top - dropdownRefRect.height - pointerMargin - dropdownMargin;
          left = refRect.left + refRect.width / 2 - defaultArrowWidth / 2 - defaultArrowEdgeGap;

          break;
        }

        case IconMenuPosition.Bottom: {
          newArrowPosition.left = '50%';
          newArrowPosition.top = `-${defaultArrowWidth / 2}px`;
          top = refRect.top + refRect.height + pointerMargin + dropdownMargin;
          left = refRect.left + refRect.width / 2 - dropdownRefRect.width / 2;

          break;
        }

        case IconMenuPosition.BottomLeft: {
          newArrowPosition.right = `${defaultArrowEdgeGap}px`;
          newArrowPosition.top = `-${defaultArrowWidth / 2}px`;
          top = refRect.top + refRect.height + pointerMargin + dropdownMargin;
          left = refRect.left + refRect.width / 2 - dropdownRefRect.width + defaultArrowWidth / 2 + defaultArrowEdgeGap;

          break;
        }

        case IconMenuPosition.BottomRight: {
          newArrowPosition.left = `${defaultArrowEdgeGap}px`;
          newArrowPosition.top = `-${defaultArrowWidth / 2}px`;
          top = refRect.top + refRect.height + pointerMargin + dropdownMargin;
          left = refRect.left + refRect.width / 2 - defaultArrowWidth / 2 - defaultArrowEdgeGap;

          break;
        }

        case IconMenuPosition.Left:
        default: {
          newArrowPosition.top = `calc(50% - ${defaultArrowWidth / 2}px)`;
          newArrowPosition.right = `-${defaultArrowWidth / 2}px`;
          top = refRect.top + refRect.height / 2 - dropdownRefRect.height / 2;
          left = refRect.left - dropdownRefRect.width - pointerMargin - dropdownMargin;
        }
      }

      setDropdownStyle({
        top,
        left
      });
      setMenuPointerStyle(newArrowPosition);
    }
  }, [isComponentVisible, ref, position, dropdownMargin, width]);

  const handleClickIcon = () => {
    setIsComponentVisible(!isComponentVisible);
  };

  return (
    <>
      <IconMenuWrapper ref={ref} margin={margin}>
        <DropdownIcon role="button" tabIndex={0} onClick={handleClickIcon} className={`testId-dropdownIcon ${iconClassName} ${disabled && 'disabled'}`}>
          {title}
          {icon && <FontAwesomeIcon icon={icon} color={iconColor} size="lg" />}
        </DropdownIcon>
        {isComponentVisible && (
          <IconMenuDropDownWrapper ref={dropdownRef} visible={isComponentVisible && !!dropdownStyle} showTail={showTail} style={dropdownStyle || undefined}>
            <IconMenuContent className="testId-dropdownItems">
              {!!hasPointer && <IconMenuPointer style={menuPointerStyle} />}
              {items.map((item, i) => (
                <IconMenuDropDownItem key={`${item.value}-${i}`} className={item.className} onMouseUp={item.onClick} data-value={item.value}>
                  {item.title}
                </IconMenuDropDownItem>
              ))}
            </IconMenuContent>
          </IconMenuDropDownWrapper>
        )}
      </IconMenuWrapper>
    </>
  );
};

export default IconMenu;
