import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import i18next from 'i18next';
import { get } from 'lodash';

import { ThemeProvider } from 'styled-components';
import {
  PaginatorContainer,
  MaxPerPageDropdown,
  DropdownButton,
  DropdownList,
  DropdownItem,
  DropdownText,
  PagesHandler,
  PageSwitcher,
  PagesDisplay,
  PaginatorInfo,
  ElementsInfo,
  SelectedItemsInfo,
  SelectedItemsCount,
  Icon,
} from './styledComponents';

import { Props } from './interfaces';

import ArrowGrey from '../images/icon-arrow-grey.svg';
import DropdownGrey from '../images/icon-dropdown-grey.svg';
import ArrowLeftBlue from '../images/icon-arrow-left-blue.svg';
import CheckMarkBlue from '../images/icon-check-blue.svg';

import DropdownDark from '../images/icon-dropdown-dark.svg';
import ArrowLeftDark from '../images/icon-arrow-left-dark.svg';
import CheckMarkDark from '../images/icon-check-dark.svg';

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

const icons = {
  blue: {
    arrow: ArrowGrey,
    check: CheckMarkBlue,
    dropdown: DropdownGrey,
    navigation: ArrowLeftBlue,
  },
  dark: {
    arrow: ArrowGrey,
    check: CheckMarkDark,
    dropdown: DropdownDark,
    navigation: ArrowLeftDark,
  },
};

const Paginator = (props: Props): JSX.Element => {
  const {
    theme,
    isLoading,
    currentPage,
    setCurrentPage,
    itemsCount,
    selectedItemsCount,
    maxPerPage,
    setMaxPerPage,
    maxPerPageOptions,
    hideAllPerPageOption,
  } = props;

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

  const [isDropdownOpen, setIsDropdownOpen] = useState(false);

  const dropdownRef = useRef<HTMLInputElement>(null);

  const getMaxPage = () => {
    return Math.ceil(itemsCount / maxPerPage);
  };

  const getFirstElementOfPage = () => {
    return (currentPage - 1) * maxPerPage + 1;
  };

  const getLastElementOfPage = () => {
    if (currentPage * maxPerPage > itemsCount) {
      return itemsCount;
    }
    return currentPage * maxPerPage;
  };

  const setPreviousPage = () => {
    if (currentPage <= 1) {
      return;
    }
    setCurrentPage(currentPage - 1);
  };

  const setNextPage = () => {
    if (currentPage >= getMaxPage()) {
      return;
    }
    setCurrentPage(currentPage + 1);
  };

  const toggle = () => {
    setIsDropdownOpen(!isDropdownOpen);
  };

  const close = () => {
    setIsDropdownOpen(false);
  };

  const handleMaxPerPageChange = (option) => {
    setMaxPerPage(option);
    close();
  };

  useEffect(() => {
    function handleClickOutside(event) {
      const currentRef = get(dropdownRef, 'current');
      if (currentRef && !currentRef.contains(event.target)) {
        close();
      }
    }

    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [dropdownRef]);

  return (
    <ThemeProvider theme={updatedTheme}>
      <PaginatorContainer>
        <PaginatorInfo>
          <MaxPerPageDropdown ref={dropdownRef}>
            <DropdownButton
              disabled={isLoading}
              onClick={() => !isLoading && toggle()}
            >
              {maxPerPage === itemsCount
                ? i18next.t('COMPONENT_LIST_VIEW_PAGINATOR_PER_PAGE_ALL')
                : `${maxPerPage} ${i18next.t(
                    'COMPONENT_LIST_VIEW_PAGINATOR_PER_PAGE'
                  )}`}
              <Icon
                width={8}
                height={4}
                rotated={isDropdownOpen}
                style={{ marginLeft: '16px' }}
                src={icons[updatedTheme.pagination?.icon].dropdown}
              />
            </DropdownButton>
            {isDropdownOpen && (
              <DropdownList>
                {maxPerPageOptions.map((option) => (
                  <DropdownItem
                    key={`max-per-page-option-${option}`}
                    onClick={() => {
                      handleMaxPerPageChange(option);
                      setCurrentPage(1);
                    }}
                  >
                    <DropdownText selected={maxPerPage === option}>
                      {option}{' '}
                      {i18next.t('COMPONENT_LIST_VIEW_PAGINATOR_PER_PAGE')}
                    </DropdownText>
                    {option === maxPerPage && (
                      <Icon
                        style={{ marginLeft: '16px' }}
                        src={icons[updatedTheme.pagination?.icon].check}
                      />
                    )}
                  </DropdownItem>
                ))}
                {!hideAllPerPageOption && (
                  <DropdownItem
                    onClick={() => {
                      handleMaxPerPageChange(itemsCount);
                      setCurrentPage(1);
                    }}
                  >
                    <DropdownText selected={maxPerPage === itemsCount}>
                      {i18next.t('COMPONENT_LIST_VIEW_PAGINATOR_PER_PAGE_ALL')}
                    </DropdownText>
                    {itemsCount === maxPerPage && (
                      <Icon
                        style={{ marginLeft: '16px' }}
                        src={icons[updatedTheme.pagination?.icon].check}
                      />
                    )}
                  </DropdownItem>
                )}
              </DropdownList>
            )}
          </MaxPerPageDropdown>
          <ElementsInfo>
            {getFirstElementOfPage()} - {getLastElementOfPage()}{' '}
            {i18next.t('COMPONENT_LIST_VIEW_PAGINATOR_ON')} {itemsCount}
          </ElementsInfo>
          {!!selectedItemsCount && (
            <SelectedItemsInfo>
              <Icon src={icons[updatedTheme.pagination?.icon].arrow} />
              <SelectedItemsCount>
                {selectedItemsCount}{' '}
                {i18next.t('COMPONENT_LIST_VIEW_PAGINATOR_SELECTED')}
              </SelectedItemsCount>
            </SelectedItemsInfo>
          )}
        </PaginatorInfo>
        <PagesHandler>
          <PageSwitcher
            disabled={isLoading || currentPage === 1}
            border="right"
            onClick={() => !isLoading && setPreviousPage()}
          >
            <Icon
              width={5}
              height={8}
              src={icons[updatedTheme.pagination?.icon].navigation}
            />
          </PageSwitcher>
          <PagesDisplay>
            {currentPage} / {getMaxPage()}
          </PagesDisplay>
          <PageSwitcher
            disabled={isLoading || currentPage === getMaxPage()}
            border="left"
            onClick={() => !isLoading && setNextPage()}
          >
            <Icon
              width={5}
              height={8}
              src={icons[updatedTheme.pagination?.icon].navigation}
              rotated
            />
          </PageSwitcher>
        </PagesHandler>
        <PaginatorInfo hidden />
      </PaginatorContainer>
    </ThemeProvider>
  );
};

Paginator.propTypes = {
  isLoading: PropTypes.bool,
  itemsCount: PropTypes.number.isRequired,
  selectedItemsCount: PropTypes.number,
  maxPerPage: PropTypes.number.isRequired,
  maxPerPageOptions: PropTypes.arrayOf(PropTypes.number),
  // eslint-disable-next-line react/forbid-prop-types
  theme: PropTypes.objectOf(PropTypes.any),
  setMaxPerPage: PropTypes.func,
  setCurrentPage: PropTypes.func,
  currentPage: PropTypes.number,
  hideAllPerPageOption: PropTypes.bool,
};

Paginator.defaultProps = {
  isLoading: false,
  selectedItemsCount: 0,
  theme: null,
  setMaxPerPage: () => {},
  setCurrentPage: () => {},
  currentPage: 0,
  maxPerPageOptions: [10, 20, 50, 100],
  hideAllPerPageOption: false,
};

export default Paginator;
