import React from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
import Spinner from './../Spinner';
import Alert from '../Alert';

const propTypes = {
  data: PropTypes.oneOfType([
    PropTypes.array,
    PropTypes.object
  ]),
  loading: PropTypes.bool.isRequired,
  error: PropTypes.object,
  label: PropTypes.string.isRequired,
  children: PropTypes.func,
  renderEmpty: PropTypes.bool,
  componentAlertWrapper: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.element,
    PropTypes.node,
    PropTypes.object,
    PropTypes.func
  ]),
  className: PropTypes.string
};

const defaultProps = {
  data: null,
  error: null,
  children: null,
  renderEmpty: false,
  componentAlertWrapper: 'div',
  className: undefined
};

// This component uses the prop Component to pass the children
// coz otherwise it is not elegant to do the propTypes in the
// included Component, some prop inject may be only available
// when the loading is done or no error occured for instance
class UIStates extends React.Component {
  renderLoading() {
    const { componentAlertWrapper: AlertWrapper, className } = this.props;
    return (
      <AlertWrapper className={className} {...omit(this.props, Object.keys(propTypes))}>
        <Spinner />
      </AlertWrapper>
    );
  }
  renderError() {
    const { label, componentAlertWrapper: AlertWrapper, className } = this.props;
    return (
      <AlertWrapper className={className} {...omit(this.props, Object.keys(propTypes))}>
        <Alert type="danger">{`Couldn't load ${label}`}</Alert>
      </AlertWrapper>
    );
  }
  renderEmpty() {
    const { label, componentAlertWrapper: AlertWrapper, className } = this.props;
    return (
      <AlertWrapper className={className} {...omit(this.props, Object.keys(propTypes))}>
        <Alert type="info">No {label} has been found.</Alert>
      </AlertWrapper>
    );
  }
  render() {
    const { data, loading, error, children, renderEmpty, ...props } = this.props;
    if (loading) return this.renderLoading();
    if (error) return this.renderError();
    if (!renderEmpty) {
      if (data === null || data === undefined || (Array.isArray(data) && data.length === 0)) {
        return this.renderEmpty();
      }
    }
    return children(...props);
  }
}

UIStates.propTypes = propTypes;
UIStates.defaultProps = defaultProps;

export default UIStates;
