import React from 'react';
import { bool, string, func, arrayOf, shape } from 'prop-types';
import styled from 'styled-components';
import { media, REM_FONT_SIZE__SM, REM_FONT_SIZE_NORMAL, GRAY_X11 } from '@vincent_za/styles';
import { CheckboxField } from '../../form';

import { Row, Cell } from '../index';

export const TableStyled = styled.table`
  display: ${props => props.isInitial || props.isHidden ? 'none' : 'table'};
  width: 100%;
  font-size: ${REM_FONT_SIZE__SM};
  color: ${GRAY_X11};
  line-height: normal;

  ${media.sm`
    font-size: ${REM_FONT_SIZE_NORMAL};
  `};
`;

function tableHOC(WrappedComponent) {
  return class Table extends React.Component {
    static propTypes = {
      id: string,
      isChecked: bool,
      tableHeaders: arrayOf(shape({})),
      list: arrayOf(shape({})).isRequired,
      isMinimal: bool,
      isNoHeader: bool,
      isInitial: bool,
      isHidden: bool,
      onChange: func,
      className: string,
    };

    static defaultProps = {
      isMinimal: false,
      isNoHeader: false,
      id: undefined,
      isChecked: false,
      isInitial: false,
      isHidden: false,
      tableHeaders: [],
      onChange() {},
      className: undefined,
    };

    constructor(props) {
      super(props);
      this.state = {
        tableHeaders: props.tableHeaders,
        list: props.list,
        keyToSort: undefined,
      };
      this.sorting = (tableHeaders, list, keyToSort) => list.sort((a, b) => {
        if (!keyToSort) return 0;
        const sortAscending = tableHeaders.find(header => header.keyToSort === keyToSort).asc;
        if (a[keyToSort] > b[keyToSort]) return sortAscending ? 1 : -1;
        if (a[keyToSort] < b[keyToSort]) return sortAscending ? -1 : 1;
        return 0;
      });
    }

    shouldComponentUpdate(nextProps, nextState) {
      if (nextState.tableHeaders !== this.state.tableHeaders) return true;
      if (nextState.keyToSort !== this.state.keyToSort) return true;
      if (nextState.list !== this.state.list) return true;

      if (nextProps.isChecked !== this.props.isChecked) return true;
      if (nextProps.tableHeaders !== this.props.tableHeaders) return true;
      if (nextProps.list !== this.props.list) return true;
      if (nextProps.isInitial !== this.props.isInitial) return true;
      if (nextProps.isHidden !== this.props.isHidden) return true;
      return false;
    }

    componentDidUpdate(prevProps) {
      const { state: { keyToSort, tableHeaders }, props: { list } } = this;
      if (prevProps.list !== list) {
        this.setState({
          list: this.sorting(tableHeaders, list, keyToSort),
        });
      }
    }

    onSort = ({ keyToSort = this.state.keyToSort }) => {
      const { list } = this.state;
      const tableHeaders = this.state.tableHeaders.map((header) => {
        if (header.keyToSort === keyToSort) {
          return {
            ...header,
            asc: !header.asc,
            isSorted: true,
          };
        }
        return {
          ...header,
          asc: false,
          isSorted: false,
        };
      });

      this.setState({
        tableHeaders,
        list: this.sorting(tableHeaders, list, keyToSort),
        keyToSort,
      });
    }

    render() {
      const { tableHeaders } = this.state;
      const { isMinimal, isNoHeader, id, isChecked, onChange, isInitial, isHidden, className } = this.props;

      return (
        <TableStyled isMinimal={isMinimal} isInitial={isInitial} isHidden={isHidden} className={className}>
          <tbody>
            {
              !isNoHeader &&
              <Row isHeader>
                {
                  tableHeaders.map(({ isCheckboxWrap, title, isSorted, isSortable, asc, keyToSort, noTitleKey }) => (
                    <Cell
                      title={title}
                      isHeader
                      isSorted={isSorted}
                      isSortable={isSortable}
                      asc={asc}
                      onClick={() => keyToSort ? this.onSort({ keyToSort }) : false}
                      key={title || noTitleKey}
                    >
                      {isCheckboxWrap && <CheckboxField id={id} isChecked={isChecked} onChange={onChange} />}
                    </Cell>
                  ))
                }
              </Row>
            }
            <WrappedComponent {...this.props} {...this.state} />
          </tbody>
        </TableStyled>
      );
    }
  };
}

export default tableHOC;
