import PropTypes from "prop-types";
import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect, Route } from "react-router-dom";
import { Loader } from "semantic-ui-react";

import { sendGetSelfUserRequest } from "../../actions/user/saga.actions";

const propTypes = {
  userToken: PropTypes.string.isRequired,
  selfUser: PropTypes.object.isRequired,
  isSendingUserRequest: PropTypes.bool.isRequired,
  path: PropTypes.string.isRequired,
  component: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
    .isRequired,
  dispatch: PropTypes.func.isRequired
};

class PrivateRoute extends Component {
  componentWillMount() {
    const { dispatch, userToken, selfUser } = this.props;
    // If the user token exists and the self user object isn't loaded, dispatch
    if (userToken && Object.keys(selfUser).length === 0) {
      dispatch(sendGetSelfUserRequest());
    }
  }

  render() {
    const {
      userToken,
      selfUser,
      isSendingUserRequest,
      component,
      ...rest
    } = this.props;
    // If the user token exists and
    // * self user object isn't loaded yet or
    // * we are still sending user request
    // show loading spinner
    if (
      userToken && (Object.keys(selfUser).length === 0 || isSendingUserRequest)
    ) {
      return <Loader active />;
    }
    // If the user exists but they aren't a client or provider yet, confirm-registration
    if (
      userToken &&
      Object.keys(selfUser).length &&
      (!selfUser.client || !selfUser.provider)
    ) {
      return <Redirect to="/user/complete-registration" />;
    }
    return (
      <Route
        {...rest}
        render={props => {
          if (!!userToken) return React.createElement(component, props);
          return <Redirect to="/auth/login" />;
        }}
      />
    );
  }
}

PrivateRoute.propTypes = propTypes;

const mapStateToProps = state => ({
  userToken: state.auth.userToken,
  selfUser: state.user.selfUser,
  isSendingUserRequest: state.user.isSendingUserRequest
});

export default connect(mapStateToProps)(PrivateRoute);
