import React from 'react';
import { bool, number, array, object, func } from 'prop-types';
import styled from 'styled-components';
import {
  media,
  REM_UNIT_MD,
  REM_UNIT_XLG,
  REM_FONT_SIZE_LG,
  FONT_BOLD,
  SONIC_SILVER,
  CHARLESTON_GREEN,
  GRAY_X11,
  LIGHT_SEA_GREEN,
} from '@vincent_za/styles';
import { chevronLeftSvg, chevronRightSvg } from '@vincent_za/assets';
import Svg from '../../Svg/component';

import { Table } from '../index';

const Wrap = styled.div``;

const MobileControls = styled.ul`
  display: ${props => props.isVisible ? 'flex' : 'none'};
  margin-top: ${REM_UNIT_XLG};
  justify-content: center;

  ${media.sm`
    display: none;
  `};
`;

const Controls = styled.ul`
  display: none;
  justify-content: center;
  margin-top: ${REM_UNIT_XLG};
  height: 3.6rem;
  user-select: none;

  ${media.sm`
    display: ${props => props.isVisible ? 'flex' : 'none'};
  `};
`;

const Control = styled.li`
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 3.6rem;
  font-size: ${REM_FONT_SIZE_LG};
  font-family: ${FONT_BOLD};
  cursor: pointer;
  color: ${props => props.isActive ? LIGHT_SEA_GREEN : SONIC_SILVER};

  ${props => props.isMobile && `
    margin: 0 ${REM_UNIT_MD};
    width: auto;
  `};

  ${props => props.isDisabled && `
    pointer-events: none;
    opacity: 0.3;
    cursor: not-allowed;
  `};

  ${props => props.isViewChange && `
    box-shadow: inset 0px 0px 0 3px ${CHARLESTON_GREEN}, inset 0px 0px 0px 4px #5d5d5d;
  `};

  &:hover {
    ${props => !props.isActive && `color: ${GRAY_X11}`};
    ${props => props.isGroup && `
      svg {
        fill: ${GRAY_X11};
      };
    `};
    ${props => props.isViewChange && `
      box-shadow: inset 0px 0px 0 3px ${CHARLESTON_GREEN}, inset 0px 0px 0px 4px ${GRAY_X11};
    `};
  };
`;

const Icon = styled(Svg)`
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  ${props => props.isFirst && 'margin-right: -1rem'};
  ${props => props.isLast && 'margin-left: -1rem'};

  svg {
    fill: ${SONIC_SILVER};
  };

  &:hover {
    svg {
      fill: ${GRAY_X11};
    };
  };
`;

class Pagination extends React.Component {
  constructor(props) {
    super(props);
    this.resetDefaultPageLinks();

    this.state = {
      pageLinks: this.setPageLinks(),
      activePageNumber: 1,
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.list.length !== this.props.list.length) {
      this.resetDefaultPageLinks();
      this.setState({
        pageLinks: this.setPageLinks(nextProps.list),
        activePageNumber: 1,
      });
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (nextState.pageLinks !== this.state.pageLinks) return true;
    if (nextState.activePageNumber !== this.state.activePageNumber) return true;
    if (nextProps.isHidden !== this.props.isHidden) return true;
    if (nextProps.list !== this.props.list) return true;
    if (nextProps.headerRowTemplate !== this.props.headerRowTemplate) return true;
    if (nextProps.contentRowTemplate !== this.props.contentRowTemplate) return true;
    if (nextProps.isInitial !== this.props.isInitial) return true;
    return false;
  }

  onNavigateToPage = (selectedPageNumber) => {
    const numberOfPages = this.getNumberOfPages();
    const addOne = item => item + 1;
    const removeItems = ((item, amount) => item >= selectedPageNumber - amount);
    const isViewChange = !this.pageLinksActive.includes(selectedPageNumber);
    const numberOfPagesFromEnd = numberOfPages - selectedPageNumber;

    if (selectedPageNumber <= 10 && isViewChange) {
      this.pageLinksActive = [...Array(10).keys()].map(addOne);
    } else if (selectedPageNumber >= numberOfPages - 9 && isViewChange) {
      this.pageLinksActive = [...Array(numberOfPages).keys()]
        .map(addOne)
        .filter(i => removeItems(i, (9 - numberOfPagesFromEnd)));
    } else if (isViewChange) {
      this.pageLinksActive = [...Array(selectedPageNumber + 5).keys()]
        .map(addOne)
        .filter(i => removeItems(i, 5));
    }

    this.setState({
      activePageNumber: selectedPageNumber,
      pageLinks: this.setPageLinks(),
    });
  }

  getNumberOfPages = (updatedList = this.props.list) => Math.ceil(updatedList.length / this.props.pageLimit);

  setPageLinks = (updatedList = this.props.list) => {
    const updatedPageLinks = [...new Set([...this.pageLinksActive, ...this.pageLinksExponential])];
    const numberOfPages = this.getNumberOfPages(updatedList);
    return updatedPageLinks.filter(item => item <= numberOfPages).sort((a, b) => a - b);
  }

  resetDefaultPageLinks = () => {
    this.pageLinksActive = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    this.pageLinksExponential = [20, 40, 80, 160, 320];
  }

  render() {
    const { pageLinks, activePageNumber } = this.state;
    const { isHidden, list, isInitial, pageLimit, headerRowTemplate, contentRowTemplate } = this.props;
    const firstPage = 1;
    const lastPage = this.getNumberOfPages();
    const isLoaded = pageLinks.length > 1;

    return (
      <Wrap>
        <Table isHidden={isHidden} isInitial={isInitial}>
          {headerRowTemplate}
          {list.slice((activePageNumber - 1) * pageLimit, (activePageNumber * pageLimit)).map(contentRowTemplate)}
        </Table>
        <MobileControls isVisible={isLoaded && !isHidden}>
          <Control
            isMobile
            isDisabled={activePageNumber === firstPage}
            onClick={() => this.onNavigateToPage(activePageNumber - 1)}
          >
            Previous
          </Control>
          <Control
            isMobile
            isDisabled={activePageNumber === lastPage}
            onClick={() => this.onNavigateToPage(activePageNumber + 1)}
          >
            Next
          </Control>
        </MobileControls>
        <Controls isVisible={isLoaded && !isHidden}>
          <Control
            isGroup
            isDisabled={activePageNumber === firstPage}
            onClick={() => this.onNavigateToPage(firstPage)}
          >
            <Icon isFirst svg={chevronLeftSvg} />
            <Icon svg={chevronLeftSvg} />
          </Control>
          <Control
            isDisabled={activePageNumber === firstPage}
            onClick={() => this.onNavigateToPage(activePageNumber - 1)}
          >
            <Icon svg={chevronLeftSvg} />
          </Control>
          {
            this.state.pageLinks.map(pageNumber => (
              <Control
                isActive={pageNumber === activePageNumber}
                isViewChange={!this.pageLinksActive.includes(pageNumber)}
                onClick={() => this.onNavigateToPage(pageNumber)}
                key={pageNumber}
              >
                {pageNumber}
              </Control>
            ))
          }
          <Control
            isDisabled={activePageNumber === lastPage}
            onClick={() => this.onNavigateToPage(activePageNumber + 1)}
          >
            <Icon svg={chevronRightSvg} />
          </Control>
          <Control
            isGroup
            isDisabled={activePageNumber === lastPage}
            onClick={() => this.onNavigateToPage(lastPage)}
          >
            <Icon svg={chevronRightSvg} />
            <Icon isLast svg={chevronRightSvg} />
          </Control>
        </Controls>
      </Wrap>
    );
  }
}

Pagination.propTypes = {
  isHidden: bool,
  pageLimit: number,
  list: array.isRequired,
  headerRowTemplate: object.isRequired,
  contentRowTemplate: func.isRequired,
  isInitial: bool,
};

Pagination.defaultProps = {
  isHidden: false,
  isInitial: false,
  pageLimit: 14,
};

export default Pagination;
