/* eslint-disable jsx-a11y/no-static-element-interactions */
import React, { Fragment, useState } from 'react';
import PropTypes from 'prop-types';
import { get } from 'lodash';

import {
  IconButton,
  Icon,
  Box,
  ItemContainer,
  ActionItem,
  IconContainer,
  Circle,
  CheckBoxContainer,
} from '../../styledComponents';

import { Props } from './interfaces';
import { EllipsisAction } from '../../interfaces';

import Marker from './components/Marker';
import Dropdown from '../Dropdown/index';
import Checkbox from '../../../Checkbox/index';
import RadioButton from '../../../RadioButton/index';

import IconEllipsisBlue from '../../../images/icon-ellipsis-blue.svg';
import IconEllipsisDark from '../../../images/icon-ellipsis-dark-small.svg';
import IconEllipsisWhite from '../../../images/icon-ellipsis-white-small.svg';

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

import ListViewItem from '../ListViewItem';

const icons = {
  blue: {
    ellipsis: IconEllipsisBlue,
    ellipsisHover: IconEllipsisWhite,
  },
  dark: {
    ellipsis: IconEllipsisDark,
    ellipsisHover: IconEllipsisWhite,
  },
};

const ListViewContent = (props: Props): JSX.Element => {
  const {
    theme,
    columns,
    data,
    selectRow,
    isSelectable,
    actionsOnHover,
    rowActions,
    actionOnClick,
    disableMultipleSelection,
    markerConfiguration,
  } = props;

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

  const [showActionOnHover, setShowActionOnHover] = useState<number | null>(
    null
  );
  const [isButtonHovered, setIsButtonHovered] = useState<number | null>(null);

  const [isActionOpened, setIsActionOpened] = useState<number | null>(null);

  const displayEllipsisButton = (index) => {
    return (
      <IconContainer>
        {index === showActionOnHover || index === isActionOpened ? (
          <Circle selected={index === isActionOpened}>
            <Icon hovered src={icons[updatedTheme.item?.icon].ellipsisHover} />
          </Circle>
        ) : (
          <Icon src={icons[updatedTheme.item?.icon].ellipsis} />
        )}
      </IconContainer>
    );
  };

  const handleClick = (event) => (clickFunction, row, index) => {
    if (row.isNotSelectable) {
      return;
    }

    if (event && event.stopPropagation) {
      event.stopPropagation();
    }
    clickFunction(row, index);
  };

  const injectValueInAction = (actions: EllipsisAction[], value: unknown) => {
    return actions.map((action) => ({
      ...action,
      ...(action.actionIcon
        ? { actionIcon: () => action.actionIcon && action.actionIcon(value) }
        : {}),
      ...(action.isDisabled
        ? { isDisabled: () => action.isDisabled && action.isDisabled(value) }
        : { isDisabled: () => false }),
      ...(action.isHidden
        ? { isHidden: () => action.isHidden && action.isHidden(value) }
        : { isHidden: () => false }),
      ...(action.isHighlighted
        ? {
            isHighlighted: () =>
              action.isHighlighted && action.isHighlighted(value),
          }
        : { isHighlighted: () => false }),
      ...(action.disabledTooltipText
        ? {
            disabledTooltipText: () =>
              action.disabledTooltipText && action.disabledTooltipText(value),
          }
        : {}),
      actionLabel: () => action.actionLabel(value),
      handleAction: () => action.handleAction(value),
    }));
  };

  const renderActionOnHover = (item, index) => {
    const actions = actionsOnHover(item);

    return (
      <ItemContainer key={`row-column-action-${item.id}`} narrow>
        {index === showActionOnHover &&
          !!actionsOnHover &&
          !!actions.length &&
          actions.map((action, indexActionHover) => (
            <ActionItem key={`icon-button-${action.icon}}`} marginLeft={5}>
              <IconButton
                onClick={(e) =>
                  handleClick(e)(action.handleAction, item, index)
                }
                onMouseEnter={() => setIsButtonHovered(indexActionHover)}
                onMouseLeave={() => setIsButtonHovered(null)}
              >
                <Icon
                  width={15}
                  height={15}
                  src={
                    action.iconOnHover && isButtonHovered === indexActionHover
                      ? action.iconOnHover
                      : action.icon
                  }
                />
              </IconButton>
            </ActionItem>
          ))}
      </ItemContainer>
    );
  };

  return (
    <>
      {data &&
        data.map((item, index) => {
          return (
            <Fragment key={`fragment-${item.id}`}>
              {markerConfiguration && !markerConfiguration.isHidden(item) && (
                <Marker
                  extraMarginTop={index === 0}
                  icon={markerConfiguration.icon.src}
                  color={markerConfiguration.backgroundColor}
                />
              )}
              <Box
                hasCheckbox={isSelectable || disableMultipleSelection}
                key={`row-${item.id}`}
                highlighted={!!item.isRowSelected}
                hovered={
                  !item.isNotSelectable &&
                  (index === showActionOnHover || index === isActionOpened)
                }
                style={{
                  backgroundColor:
                    item.isNotSelectable &&
                    updatedTheme.item.disabled.backgroundColor,
                }}
                clickable={!!actionOnClick}
                hoverable={!!actionOnClick}
                onMouseEnter={() => setShowActionOnHover(index)}
                onMouseLeave={() => setShowActionOnHover(null)}
                onClick={() => actionOnClick && actionOnClick(item, index)}
              >
                {isSelectable && !disableMultipleSelection && (
                  <CheckBoxContainer
                    isDisabled={item.isNotSelectable}
                    onClick={(e) => handleClick(e)(selectRow, item, index)}
                    theme={getTheme(theme, 'checkbox')}
                  >
                    <Checkbox
                      theme={theme}
                      isChecked={!!item.isRowSelected}
                      shape="square"
                      handleClick={() => {}}
                      isDisabled={item.isNotSelectable}
                    />
                  </CheckBoxContainer>
                )}
                {disableMultipleSelection && (
                  <CheckBoxContainer
                    onClick={(e) => handleClick(e)(selectRow, item, index)}
                    theme={getTheme(theme, 'checkbox')}
                  >
                    <RadioButton
                      theme={theme}
                      value={item.id}
                      selected={!!item.isRowSelected && item.id}
                      onChange={(e) => handleClick(e)(selectRow, item, index)}
                      size="small"
                      isReadOnly={item.isNotSelectable}
                    />
                  </CheckBoxContainer>
                )}
                {columns &&
                  columns.map(
                    ({
                      name,
                      propertyKey,
                      large,
                      minWidth,
                      narrow,
                      render,
                      displayBigger,
                      hidden,
                    }) => {
                      const value = get(item, propertyKey);

                      if (hidden) {
                        return <Fragment key={`row-column-${name}`} />;
                      }

                      return (
                        <ItemContainer
                          key={`row-column-${name}`}
                          large={large}
                          minWidth={minWidth}
                          narrow={narrow}
                          narrowSidePadding={disableMultipleSelection}
                        >
                          <ListViewItem
                            render={render}
                            item={item}
                            value={value}
                            displayBigger={displayBigger}
                          />
                        </ItemContainer>
                      );
                    }
                  )}
                {!!actionsOnHover && renderActionOnHover(item, index)}
                {rowActions && !!rowActions.length && (
                  <ItemContainer key="row-column-ellipsis" narrow minWidth="58">
                    <ActionItem marginRight={13}>
                      <Dropdown
                        actions={injectValueInAction(rowActions, item)}
                        customButton={displayEllipsisButton}
                        setIsActionOpened={setIsActionOpened}
                        index={index}
                      />
                    </ActionItem>
                  </ItemContainer>
                )}
              </Box>
            </Fragment>
          );
        })}
    </>
  );
};

ListViewContent.propTypes = {
  columns: PropTypes.arrayOf(
    PropTypes.shape({
      render: PropTypes.func,
      name: PropTypes.string.isRequired,
      propertyKey: PropTypes.string.isRequired,
      large: PropTypes.bool,
      minWidth: PropTypes.number,
      displayBigger: PropTypes.bool,
    })
  ),
  // eslint-disable-next-line react/forbid-prop-types
  data: PropTypes.arrayOf(PropTypes.object),
  actionsOnHover: PropTypes.func,
  rowActions: PropTypes.arrayOf(
    PropTypes.shape({
      actionLabel: PropTypes.func.isRequired,
      handleAction: PropTypes.func.isRequired,
      actionIcon: PropTypes.func,
      render: PropTypes.func,
      disabledTooltipText: PropTypes.func,
    })
  ),
  selectRow: PropTypes.func.isRequired,
  isSelectable: PropTypes.bool.isRequired,
  actionOnClick: PropTypes.func,
  // eslint-disable-next-line react/forbid-prop-types
  theme: PropTypes.objectOf(PropTypes.any),
  markerConfiguration: PropTypes.shape({
    isHidden: PropTypes.func.isRequired,
    backgroundColor: PropTypes.string.isRequired,
    icon: PropTypes.shape({
      src: PropTypes.string.isRequired,
    }),
  }),
};

ListViewContent.defaultProps = {
  data: [],
  columns: [],
  actionsOnHover: null,
  rowActions: null,
  actionOnClick: null,
  theme: null,
  markerConfiguration: null,
};

export default ListViewContent;
