"use strict";

exports.__esModule = true;
exports.default = Vote;
exports.voteActionTypes = void 0;

var _react = _interopRequireWildcard(require("react"));

var _BaseDialog = _interopRequireDefault(require("../../../../shared/BaseDialog"));

var _reactIntl = require("react-intl");

var _material = require("@mui/material");

var _reactInfiniteScrollComponent = _interopRequireDefault(require("react-infinite-scroll-component"));

var _Icon = _interopRequireDefault(require("@mui/material/Icon"));

var _Skeleton = _interopRequireDefault(require("@mui/material/Skeleton"));

var _LoadingButton = _interopRequireDefault(require("@mui/lab/LoadingButton"));

var _CentralProgress = _interopRequireDefault(require("../../../../shared/CentralProgress"));

var _User = _interopRequireDefault(require("../../../User"));

var _Errors = require("../../../../constants/Errors");

var _styles = require("@mui/material/styles");

var _classnames = _interopRequireDefault(require("classnames"));

var _notistack = require("notistack");

var _core = require("@selfcommunity/core");

var _useThemeProps = _interopRequireDefault(require("@mui/material/styles/useThemeProps"));

const _excluded = ["className", "feedObjectId", "feedObject", "feedObjectType", "withAudience", "withAction", "inlineAction"];

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

/**
 * We have complex state logic that involves multiple sub-values,
 * so useReducer is preferable to useState.
 * Define all possible auth action types label
 * Use this to export actions and dispatch an action
 */
const voteActionTypes = {
  LOADING: '_loading_votes',
  REQUEST_VOTES_LOADING: '_request_votes_loading',
  REQUEST_VOTES_SUCCESS: '_request_votes_success',
  REQUEST_VOTES_FAILED: '_request_votes_failed',
  TOGGLE_VOTE_DIALOG: '_toggle_vote_dialog',
  REFRESHING_VOTES: '_refreshing_votes',
  VOTING: '_voting',
  REQUEST_VOTING_SUCCESS: '_request_vote_success'
};
/**
 * votesReducer manage the state of authentication
 * update the state base on action type
 * @param state
 * @param action
 */

exports.voteActionTypes = voteActionTypes;

function votesReducer(state, action) {
  switch (action.type) {
    case voteActionTypes.REQUEST_VOTES_LOADING:
      return Object.assign({}, state, {
        loadingVotes: true
      });

    case voteActionTypes.REQUEST_VOTES_SUCCESS:
      return {
        votes: state.refreshing ? [...state.votes] : [...state.votes, ...action.payload.data],
        loadingVotes: false,
        refreshing: false,
        voting: false,
        next: action.payload.next,
        openVotesDialog: state.openVotesDialog,
        error: null
      };

    case voteActionTypes.TOGGLE_VOTE_DIALOG:
      return Object.assign({}, state, {
        openVotesDialog: !state.openVotesDialog
      });

    case voteActionTypes.REQUEST_VOTES_FAILED:
      return Object.assign({}, state, {
        loadingVotes: false,
        error: action.payload.error,
        refreshing: false
      });

    case voteActionTypes.REFRESHING_VOTES:
      return Object.assign({}, state, {
        votes: [],
        loadingVotes: false,
        refreshing: true,
        error: null
      });

    case voteActionTypes.VOTING:
      return Object.assign({}, state, {
        voting: true,
        error: null
      });

    case voteActionTypes.REQUEST_VOTING_SUCCESS:
      return Object.assign({}, state, {
        voting: false,
        error: null
      });

    default:
      throw new Error(`Unhandled type: ${action.type}`);
  }
}
/**
 * Defines initial state
 */


function stateInitializer({
  feedObjectId = null,
  feedObject = null,
  feedObjectType = _core.SCFeedObjectTypologyType.POST
}) {
  const next = feedObjectId && feedObjectType ? `${_core.Endpoints.VotesList.url({
    type: feedObjectType,
    id: feedObjectId
  })}` : `${_core.Endpoints.VotesList.url({
    type: feedObjectType,
    id: feedObject.id
  })}`;
  return {
    votes: [],
    loadingVotes: false,
    voting: null,
    refreshing: false,
    next,
    openVotesDialog: false,
    error: null
  };
}

const PREFIX = 'SCVoteObject';
const classes = {
  root: `${PREFIX}-root`,
  divider: `${PREFIX}-divider`,
  actionButton: `${PREFIX}-action-button`,
  inline: `${PREFIX}-inline`,
  inlineActionButton: `${PREFIX}-inline-action-button`,
  viewAudienceButton: `${PREFIX}-view-audience-button`
};
const messages = (0, _reactIntl.defineMessages)({
  voteUp: {
    id: 'ui.feedObject.vote.voteUp',
    defaultMessage: 'ui.feedObject.vote.voteUp'
  },
  voteDown: {
    id: 'ui.feedObject.vote.voteDown',
    defaultMessage: 'ui.feedObject.vote.voteDown'
  },
  votes: {
    id: 'ui.feedObject.vote.votes',
    defaultMessage: 'ui.feedObject.vote.votes'
  },
  votedByMe: {
    id: 'ui.feedObject.vote.votedByMe',
    defaultMessage: 'ui.feedObject.votedByMe.you'
  },
  votedByOnlyMe: {
    id: 'ui.feedObject.vote.votedByOnlyMe',
    defaultMessage: 'ui.feedObject.votedByOnlyMe.you'
  }
});
const Root = (0, _styles.styled)(_material.Box, {
  name: PREFIX,
  slot: 'Root',
  overridesResolver: (props, styles) => styles.root
})(({
  theme
}) => ({
  display: 'flex',
  justifyContent: 'center',
  alignItems: 'center',
  flexDirection: 'column',
  [`&.${classes.inline}`]: {
    flexDirection: 'row-reverse'
  },
  [`& .${classes.inlineActionButton}`]: {
    minWidth: 30
  },
  [`& .${classes.divider}`]: {
    width: '100%',
    borderBottom: 0
  },
  [`& .${classes.viewAudienceButton}`]: {
    height: 32,
    fontSize: 15,
    textTransform: 'capitalize',
    '& p': {
      fontSize: '0.9rem'
    }
  }
}));

function Vote(inProps) {
  const props = (0, _useThemeProps.default)({
    props: inProps,
    name: PREFIX
  }); // PROPS

  const {
    className = null,
    feedObjectId = null,
    feedObject = null,
    feedObjectType = _core.SCFeedObjectTypologyType.POST,
    withAudience = true,
    withAction = true,
    inlineAction = true
  } = props,
        rest = _objectWithoutPropertiesLoose(props, _excluded); // STATE


  const {
    obj,
    setObj
  } = (0, _core.useSCFetchFeedObject)({
    id: feedObjectId,
    feedObject,
    feedObjectType
  });
  const [state, dispatch] = (0, _react.useReducer)(votesReducer, {}, () => stateInitializer({
    feedObjectId,
    feedObject,
    feedObjectType
  })); // CONTEXT

  const scContext = (0, _core.useSCContext)();
  const scUserContext = (0, _core.useSCUser)();
  const {
    enqueueSnackbar
  } = (0, _notistack.useSnackbar)(); // INTL

  const intl = (0, _reactIntl.useIntl)();
  /**
   * Fetches Votes only if obj
   */

  (0, _react.useEffect)(() => {
    if (obj && state.next && !state.loading && !state.refreshing && state.openVotesDialog) {
      dispatch({
        type: voteActionTypes.REQUEST_VOTES_LOADING
      });
      fetchVotes().then(data => {
        dispatch({
          type: voteActionTypes.REQUEST_VOTES_SUCCESS,
          payload: {
            next: data['next'],
            data: data['results']
          }
        });
      }).catch(error => {
        _core.Logger.error(_Errors.SCOPE_SC_UI, error);
      });
    }
  }, [state.openVotesDialog]);
  /**
   * Opens dialog votes
   */

  function handleToggleVotesDialog() {
    dispatch({
      type: voteActionTypes.TOGGLE_VOTE_DIALOG
    });
  }
  /**
   * fetches Votes
   */


  const fetchVotes = (0, _react.useMemo)(() => () => {
    return _core.http.request({
      url: state.next,
      method: _core.Endpoints.VotesList.method
    }).then(res => {
      if (res.status >= 300) {
        return Promise.reject(res);
      }

      return Promise.resolve(res.data);
    });
  }, [state.next]);
  /**
   * Performs vote up/down
   */

  const performVote = (0, _react.useMemo)(() => () => {
    return _core.http.request({
      url: _core.Endpoints.Vote.url({
        type: obj.type,
        id: obj.id
      }),
      method: _core.Endpoints.Vote.method
    }).then(res => {
      if (res.status >= 300) {
        return Promise.reject(res);
      }

      return Promise.resolve(res.data);
    });
  }, [obj]);
  /**
   * Performs voteUp/voteDown
   */

  function vote() {
    if (scUserContext.user) {
      if (_core.UserUtils.isBlocked(scUserContext.user)) {
        enqueueSnackbar( /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
          id: "ui.common.userBlocked",
          defaultMessage: "ui.common.userBlocked"
        }), {
          variant: 'warning',
          autoHideDuration: 3000
        });
      } else {
        if (obj && !state.voting) {
          dispatch({
            type: voteActionTypes.VOTING
          });
          performVote().then(data => {
            dispatch({
              type: voteActionTypes.REQUEST_VOTING_SUCCESS
            });
            setObj(Object.assign({}, obj, {
              voted: !obj.voted,
              vote_count: obj.voted ? obj.vote_count - 1 : obj.vote_count + 1
            }));
          }).catch(error => {
            _core.Logger.error(_Errors.SCOPE_SC_UI, error);
          });
        }
      }
    } else {
      scContext.settings.handleAnonymousAction();
    }
  }
  /**
   * Renders audience with detail dialog
   * @return {JSX.Element}
   */


  function renderAudience() {
    const {
      loadingVotes,
      votes,
      openVotesDialog
    } = state;
    let audience;

    if (withAudience) {
      if (!obj) {
        audience = /*#__PURE__*/_react.default.createElement(_material.Button, {
          variant: "text",
          size: "small",
          disabled: true,
          color: "inherit"
        }, /*#__PURE__*/_react.default.createElement(_Skeleton.default, {
          animation: "wave",
          height: 18,
          width: 50
        }));
      } else {
        audience = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_material.Button, {
          variant: "text",
          size: "small",
          onClick: handleToggleVotesDialog,
          disabled: obj.vote_count === 0,
          color: "inherit",
          classes: {
            root: classes.viewAudienceButton
          },
          startIcon: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !inlineAction && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, scUserContext.user && obj.voted ? /*#__PURE__*/_react.default.createElement(_Icon.default, {
            fontSize: "small",
            color: "primary"
          }, "thumb_up") : /*#__PURE__*/_react.default.createElement(_Icon.default, {
            fontSize: "small"
          }, "thumb_up_off_alt")))
        }, scUserContext.user && obj.voted ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, obj.vote_count === 1 ? intl.formatMessage(messages.votedByOnlyMe) : intl.formatMessage(messages.votedByMe, {
          total: obj.vote_count - 1
        })) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, `${intl.formatMessage(messages.votes, {
          total: obj.vote_count
        })}`)), openVotesDialog && /*#__PURE__*/_react.default.createElement(_BaseDialog.default, {
          title: /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
            defaultMessage: "ui.feedObject.votesDialog.title",
            id: "ui.feedObject.votesDialog.title"
          }),
          onClose: handleToggleVotesDialog,
          open: openVotesDialog
        }, loadingVotes ? /*#__PURE__*/_react.default.createElement(_CentralProgress.default, {
          size: 50
        }) : /*#__PURE__*/_react.default.createElement(_reactInfiniteScrollComponent.default, {
          dataLength: votes.length,
          next: fetchVotes,
          hasMore: Boolean(state.next),
          loader: /*#__PURE__*/_react.default.createElement(_CentralProgress.default, {
            size: 30
          }),
          height: 400,
          endMessage: /*#__PURE__*/_react.default.createElement("p", {
            style: {
              textAlign: 'center'
            }
          }, /*#__PURE__*/_react.default.createElement("b", null, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
            id: "ui.feedObject.votesDialog.noOtherLikes",
            defaultMessage: "ui.feedObject.votesDialog.noOtherLikes"
          })))
        }, /*#__PURE__*/_react.default.createElement(_material.List, null, votes.map((vote, index) => /*#__PURE__*/_react.default.createElement(_material.ListItem, {
          key: index
        }, /*#__PURE__*/_react.default.createElement(_User.default, {
          elevation: 0,
          user: vote.user,
          key: index,
          sx: {
            m: 0
          }
        })))))));
      }
    }

    return audience;
  }
  /**
   * Renders vote action if withAction==true
   * @return {JSX.Element}
   */


  function renderVoteButton() {
    const {
      voting
    } = state;
    return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, withAction && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !inlineAction && withAudience && /*#__PURE__*/_react.default.createElement(_material.Divider, {
      className: classes.divider
    }), /*#__PURE__*/_react.default.createElement(_material.Tooltip, {
      title: voting ? '' : obj.voted && scUserContext.user ? intl.formatMessage(messages.voteDown) : intl.formatMessage(messages.voteUp)
    }, /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_LoadingButton.default, {
      loading: voting,
      disabled: !obj,
      onClick: vote,
      color: "inherit",
      classes: {
        root: (0, _classnames.default)(classes.actionButton, {
          [classes.inlineActionButton]: inlineAction
        })
      }
    }, scUserContext.user && obj.voted ? /*#__PURE__*/_react.default.createElement(_Icon.default, {
      fontSize: 'large',
      color: "primary"
    }, "thumb_up") : /*#__PURE__*/_react.default.createElement(_Icon.default, {
      fontSize: 'large'
    }, "thumb_up_off_alt"))))));
  }
  /**
   * Renders vote action and audience section
   */


  return /*#__PURE__*/_react.default.createElement(Root, _extends({
    className: (0, _classnames.default)(classes.root, className, {
      [classes.inline]: inlineAction
    })
  }, rest), renderAudience(), renderVoteButton());
}