import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { getColumnClasses } from './helpers';
import { modifierCSS } from '../../../helpers';

const propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.element,
    PropTypes.arrayOf(PropTypes.element),
  ]),
  className: PropTypes.string,
  defaultClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
  headerLabels: PropTypes.arrayOf(PropTypes.node),
  preHeader: PropTypes.arrayOf(
    PropTypes.shape({ label: PropTypes.string, size: PropTypes.number })
  ),
  isBordered: PropTypes.bool,
  innerBorder: PropTypes.bool,
  isHover: PropTypes.bool,
  isLight: PropTypes.bool,
  levelBreakpoint: PropTypes.oneOf(['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl', 'xxl']),
  sortIndexes: PropTypes.arrayOf(PropTypes.number),
  onSort: PropTypes.func,
  /**
   * The component used for the root node.
   * Either a string to use a DOM element or a component.
   */
  tag: PropTypes.elementType,
};

const defaultProps = {
  children: null,
  className: '',
  defaultClassName: 'sui-o-datalist',
  headerLabels: null,
  preHeader: [],
  isBordered: false,
  innerBorder: false,
  isHover: true,
  isLight: false,
  levelBreakpoint: 'md',
  sortIndexes: null,
  onSort: () => {},
  tag: 'div',
};

export const Datalist = (props) => {
  const {
    children,
    className,
    defaultClassName,
    headerLabels,
    preHeader,
    isBordered,
    innerBorder,
    isHover,
    isLight,
    levelBreakpoint,
    sortIndexes,
    onSort,
    tag: Tag,
    ...attributes
  } = props;

  const [activeSortByIndex, setActiveSortByIndex] = useState({});

  const classes = classnames(
    defaultClassName,
    className,
    modifierCSS(levelBreakpoint, 'level-breakpoint'),
    {
      'as--sorted': sortIndexes,
      'as--inner-border': innerBorder,
      'as--bordered': isBordered,
      'as--light': isLight,
      'as--hover': isHover,
    },
  );
  const rows = (React.Children.toArray(children) || [])
    .map((row) => React.Children.toArray(row.props.children));
  const firstRow = rows[0];
  const headerClasses = firstRow ? firstRow.map((col) => getColumnClasses(col.props)) : '';

  const handleSort = (type, index) => {
    setActiveSortByIndex({
      [index]: type,
    });
    onSort(type, index);
  };

  const renderHeader = () => {
    if (!headerLabels) {
      return '';
    }

    const preHeaders = () => {
      if (preHeader.length === 0) {
        return null;
      }
      if (rows.length === 0) {
        return null;
      }
      let sizeIndex = 0;
      return preHeader.map((elem, i) => {
        sizeIndex += elem.size || 1;
        return (
          // eslint-disable-next-line react/no-array-index-key
          <div key={i} style={{ flexGrow: elem.size && elem.size.toString(), borderBottom: headerLabels[sizeIndex - 1] === '' ? 'none' : '0.0625rem solid #d9dbe3' }} className={`${headerClasses[i]} sui-o-datalist__col`}>
            {elem.label}
          </div>
        );
      }
      );
    };

    const headers = () => {
      if (rows.length === 0) {
        return headerLabels.map((x, i) => (
          // eslint-disable-next-line react/no-array-index-key
          <div key={i} className="sui-o-datalist__col">
            {x}
          </div>
        ));
      }

      return firstRow.map((x, i) => {
        const canSort = sortIndexes && sortIndexes.indexOf(i) > -1;

        return (
          <div
            // eslint-disable-next-line react/no-array-index-key
            key={i}
            className={classnames(
              headerClasses[i],
              {
                'sui-o-datalist__col--sortable': canSort,
              },
            )}
          >
            {headerLabels[i]}

            {canSort && (
              <div className="sui-o-datalist__col__sort">
                <button
                  type="button"
                  aria-label="Sort ASC"
                  className={classnames(
                    'sui-o-datalist__col__sort-up',
                    {
                      'as--active': activeSortByIndex[i] === 'ASC',
                    },
                  )}
                  onClick={() => handleSort('ASC', i)}
                />
                <button
                  type="button"
                  aria-label="Sort DESC"
                  className={classnames(
                    'sui-o-datalist__col__sort-down',
                    {
                      'as--active': activeSortByIndex[i] === 'DESC',
                    },
                  )}
                  onClick={() => handleSort('DESC', i)}
                />
              </div>
            )}
          </div>
        );
      });
    };
    return (
      <div>
        {preHeader.length
          ? (
            <div className="sui-o-datalist__preheader">
              {preHeaders()}
            </div>
          ) : ''}
        <div className="sui-o-datalist__header">
          {headers()}
        </div>
      </div>
    );
  };

  const renderRows = () => {
    if (!headerLabels) {
      return children;
    }

    return React.Children.map(children, (row) => {
      if (!row.props || !row.props.children) {
        return '';
      }

      const columns = React.Children
        .map(row.props.children, (col, index = 1) => ({
          ...col,
          props: {
            ...col.props,
            label: col.props.label === null ? headerLabels[index] : col.props.label,
          },
        }));
      return {
        ...row,
        props: {
          ...row.props,
          children: columns,
        },
      };
    });
  };

  return (
    <Tag {...attributes} className={classes}>
      {renderHeader()}
      {renderRows()}
    </Tag>
  );
};

Datalist.propTypes = propTypes;
Datalist.defaultProps = defaultProps;
