import { get } from 'lodash';
import PropTypes from 'prop-types';
import { ThemeProvider } from 'styled-components';
import React, { useRef, useState, useEffect, Fragment } from 'react';

import {
  StyledButton,
  Icon,
  DropdownList,
  CountDotContainer,
  Count,
  CountPlusIcon,
  DropdownItem,
  IconContainer,
  DropdownItemText,
  DropdownListIcon,
} from './styledComponents';

import DefaultIconDropdown from '../images/icon-dropdown-darkest.svg';

import { getTheme } from '../utils/theme';

import { Props } from './interfaces';
import COLOR from './constants';

const Button = (props: Props): JSX.Element => {
  const {
    label,
    color,
    minWidth,
    maxWidth,
    height,
    icon,
    iconOnHover,
    iconOnDisabled,
    handleClick,
    formatText,
    fontSize,
    iconOnLeft,
    fontColor,
    noBorder,
    buttonCustomStyle,
    customBackground,
    iconCustomStyle,
    animation,
    isDisabled,
    isActive,
    theme,
    type,
    actions,
    iconDropdown,
    count,
    hideActionsIcon,
  } = props;

  const dropdownRef = useRef<HTMLInputElement>(null);

  const [isDropdownOpened, setIsDropdownOpened] = useState(false);

  const updatedTheme = getTheme(theme, 'buttons');

  const MAX_VALUE_COUNT = 99;

  const isDropdownMode = actions && actions.length;

  const triggerDropdown = () => {
    setIsDropdownOpened(!isDropdownOpened);
  };

  useEffect(() => {
    function handleClickOutside(event) {
      const currentRef = get(dropdownRef, 'current');

      if (
        currentRef &&
        !currentRef.contains(event.target) &&
        setIsDropdownOpened
      ) {
        setIsDropdownOpened(false);
      }
    }

    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dropdownRef]);

  return (
    <ThemeProvider theme={updatedTheme}>
      <StyledButton
        ref={dropdownRef}
        color={color}
        onClick={(e) => {
          if (isDisabled) {
            return;
          }

          if (isDropdownMode) {
            triggerDropdown();

            return;
          }

          handleClick(e);
        }}
        formatText={formatText}
        minWidth={minWidth}
        maxWidth={maxWidth}
        height={height}
        fontSize={fontSize}
        fontColor={fontColor}
        noBorder={noBorder}
        style={buttonCustomStyle}
        customBackground={customBackground}
        fadeInOut={!!animation.fadeInOut}
        disabled={isDisabled}
        icon={icon}
        iconOnHover={iconOnHover}
        iconOnDisabled={iconOnDisabled}
        iconOnLeft={iconOnLeft}
        active={isActive}
        label={label}
        type={type}
        isDropdownOpened={isDropdownOpened}
        iconDropdown={iconDropdown}
      >
        {!!count && count > 0 && (
          <CountDotContainer>
            <Count>
              {Math.min(MAX_VALUE_COUNT, count)}
              {count > MAX_VALUE_COUNT && <CountPlusIcon>+</CountPlusIcon>}
            </Count>
          </CountDotContainer>
        )}
        {icon && iconOnLeft && (
          <Icon
            style={iconCustomStyle}
            iconOnLeft={iconOnLeft}
            alt={label}
            src={icon}
            rotation={!!animation.rotate}
          />
        )}
        {label && <div>{label}</div>}
        {icon && !iconOnLeft && (
          <Icon
            style={iconCustomStyle}
            iconOnLeft={iconOnLeft}
            alt={label}
            src={icon}
            rotation={!!animation.rotate}
          />
        )}
        {isDropdownMode && !hideActionsIcon && (
          <Icon
            alt={label}
            src={iconDropdown || DefaultIconDropdown}
            style={iconDropdown ? {} : { width: '14px', height: '6px' }}
          />
        )}
        {isDropdownOpened && (
          <DropdownList>
            {actions.map((action) => {
              if (action.isHidden) {
                return <Fragment key={`item-${action.label}`} />;
              }
              return (
                <DropdownItem
                  key={`item-${action.label}`}
                  isDisabled={action.isDisabled}
                  isHighlighted={action.isHighlighted}
                  onClick={(e) => {
                    if (action.isDisabled) {
                      e.stopPropagation();

                      return;
                    }

                    action.handleClick(e);
                  }}
                >
                  {action.icon && (
                    <IconContainer>
                      <DropdownListIcon icon={action.icon} />
                    </IconContainer>
                  )}
                  <DropdownItemText>{action.label}</DropdownItemText>
                </DropdownItem>
              );
            })}
          </DropdownList>
        )}
      </StyledButton>
    </ThemeProvider>
  );
};

Button.propTypes = {
  // eslint-disable-next-line react/forbid-prop-types
  theme: PropTypes.objectOf(PropTypes.any),
  handleClick: PropTypes.func,
  label: PropTypes.oneOfType([PropTypes.string.isRequired, PropTypes.object]),
  color: PropTypes.oneOf(Object.values(COLOR)),
  minWidth: PropTypes.number,
  maxWidth: PropTypes.number,
  height: PropTypes.number,
  icon: PropTypes.string,
  iconOnHover: PropTypes.string,
  iconOnDisabled: PropTypes.string,
  formatText: PropTypes.bool,
  fontSize: PropTypes.number,
  iconOnLeft: PropTypes.bool,
  fontColor: PropTypes.string,
  noBorder: PropTypes.bool,
  iconCustomStyle: PropTypes.objectOf(
    PropTypes.oneOfType([PropTypes.number, PropTypes.string])
  ),
  buttonCustomStyle: PropTypes.objectOf(
    PropTypes.oneOfType([PropTypes.number, PropTypes.string])
  ),
  animation: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.bool])),
  isDisabled: PropTypes.bool,
  isActive: PropTypes.bool,
  type: PropTypes.string,
  customBackground: PropTypes.string,
  actions: PropTypes.arrayOf(PropTypes.objectOf(PropTypes.any)),
  iconDropdown: PropTypes.string,
  count: PropTypes.number,
  hideActionsIcon: PropTypes.bool,
};

Button.defaultProps = {
  color: 'inpulse-default',
  icon: '',
  label: '',
  iconOnHover: '',
  iconOnDisabled: '',
  minWidth: null,
  maxWidth: null,
  height: 40,
  formatText: false,
  fontSize: 14,
  iconOnLeft: true,
  fontColor: '',
  noBorder: false,
  iconCustomStyle: { width: '16px', height: '16px' },
  buttonCustomStyle: {},
  animation: {},
  isDisabled: false,
  isActive: false,
  actions: null,
  theme: null,
  handleClick: null,
  type: 'button',
  iconDropdown: '',
  customBackground: null,
  count: 0,
  hideActionsIcon: false,
};

export default Button;
