import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { defineMessages } from 'react-intl';
import withShortcutHelper from '/imports/ui/components/shortcut-help/service';
import ExternalVideoModal from '/imports/ui/components/external-video-player/modal/container';
import RandomUserSelectContainer from '/imports/ui/components/common/modal/random-user/container';
import LayoutModalContainer from '/imports/ui/components/layout/modal/container';
import BBBMenu from '/imports/ui/components/common/menu/component';
import Styled from './styles';
import TimerService from '/imports/ui/components/timer/service';
import { colorPrimary } from '/imports/ui/stylesheets/styled-components/palette';
import { PANELS, ACTIONS, LAYOUT_TYPE } from '../../layout/enums';
import { uniqueId } from '/imports/utils/string-utils';
import { isPresentationEnabled, isLayoutsEnabled } from '/imports/ui/services/features';
import VideoPreviewContainer from '/imports/ui/components/video-preview/container';
import { screenshareHasEnded } from '/imports/ui/components/screenshare/service';

const propTypes = {
  amIPresenter: PropTypes.bool.isRequired,
  intl: PropTypes.shape({
    formatMessage: PropTypes.func.isRequired,
  }).isRequired,
  amIModerator: PropTypes.bool.isRequired,
  shortcuts: PropTypes.string,
  handleTakePresenter: PropTypes.func.isRequired,
  isTimerActive: PropTypes.bool.isRequired,
  isTimerEnabled: PropTypes.bool.isRequired,
  allowExternalVideo: PropTypes.bool.isRequired,
  stopExternalVideoShare: PropTypes.func.isRequired,
  isMobile: PropTypes.bool.isRequired,
  setMeetingLayout: PropTypes.func.isRequired,
  setPushLayout: PropTypes.func.isRequired,
  showPushLayout: PropTypes.bool.isRequired,
  isTimerFeatureEnabled: PropTypes.bool.isRequired,
  isCameraAsContentEnabled: PropTypes.bool.isRequired,
};

const defaultProps = {
  shortcuts: '',
  settingsLayout: LAYOUT_TYPE.SMART_LAYOUT,
};

const intlMessages = defineMessages({
  actionsLabel: {
    id: 'app.actionsBar.actionsDropdown.actionsLabel',
    description: 'Actions button label',
  },
  activateTimerStopwatchLabel: {
    id: 'app.actionsBar.actionsDropdown.activateTimerStopwatchLabel',
    description: 'Activate timer/stopwatch label',
  },
  deactivateTimerStopwatchLabel: {
    id: 'app.actionsBar.actionsDropdown.deactivateTimerStopwatchLabel',
    description: 'Deactivate timer/stopwatch label',
  },
  presentationLabel: {
    id: 'app.actionsBar.actionsDropdown.presentationLabel',
    description: 'Upload a presentation option label',
  },
  presentationDesc: {
    id: 'app.actionsBar.actionsDropdown.presentationDesc',
    description: 'adds context to upload presentation option',
  },
  desktopShareDesc: {
    id: 'app.actionsBar.actionsDropdown.desktopShareDesc',
    description: 'adds context to desktop share option',
  },
  stopDesktopShareDesc: {
    id: 'app.actionsBar.actionsDropdown.stopDesktopShareDesc',
    description: 'adds context to stop desktop share option',
  },
  pollBtnLabel: {
    id: 'app.actionsBar.actionsDropdown.pollBtnLabel',
    description: 'poll menu toggle button label',
  },
  pollBtnDesc: {
    id: 'app.actionsBar.actionsDropdown.pollBtnDesc',
    description: 'poll menu toggle button description',
  },
  takePresenter: {
    id: 'app.actionsBar.actionsDropdown.takePresenter',
    description: 'Label for take presenter role option',
  },
  takePresenterDesc: {
    id: 'app.actionsBar.actionsDropdown.takePresenterDesc',
    description: 'Description of take presenter role option',
  },
  startExternalVideoLabel: {
    id: 'app.actionsBar.actionsDropdown.shareExternalVideo',
    description: 'Start sharing external video button',
  },
  stopExternalVideoLabel: {
    id: 'app.actionsBar.actionsDropdown.stopShareExternalVideo',
    description: 'Stop sharing external video button',
  },
  selectRandUserLabel: {
    id: 'app.actionsBar.actionsDropdown.selectRandUserLabel',
    description: 'Label for selecting a random user',
  },
  selectRandUserDesc: {
    id: 'app.actionsBar.actionsDropdown.selectRandUserDesc',
    description: 'Description for select random user option',
  },
  layoutModal: {
    id: 'app.actionsBar.actionsDropdown.layoutModal',
    description: 'Label for layouts selection button',
  },
  shareCameraAsContent: {
    id: 'app.actionsBar.actionsDropdown.shareCameraAsContent',
    description: 'Label for share camera as content',
  },
  unshareCameraAsContent: {
    id: 'app.actionsBar.actionsDropdown.unshareCameraAsContent',
    description: 'Label for unshare camera as content',
  },
});

const handlePresentationClick = () => Session.set('showUploadPresentationView', true);

class ActionsDropdown extends PureComponent {
  constructor(props) {
    super(props);

    this.presentationItemId = uniqueId('action-item-');
    this.pollId = uniqueId('action-item-');
    this.takePresenterId = uniqueId('action-item-');
    this.timerId = uniqueId('action-item-');
    this.selectUserRandId = uniqueId('action-item-');
    this.state = {
      isExternalVideoModalOpen: false,
      isRandomUserSelectModalOpen: false,
      isLayoutModalOpen: false,
      isCameraAsContentModalOpen: false,
    };

    this.handleExternalVideoClick = this.handleExternalVideoClick.bind(this);
    this.makePresentationItems = this.makePresentationItems.bind(this);
    this.setExternalVideoModalIsOpen = this.setExternalVideoModalIsOpen.bind(this);
    this.setRandomUserSelectModalIsOpen = this.setRandomUserSelectModalIsOpen.bind(this);
    this.setLayoutModalIsOpen = this.setLayoutModalIsOpen.bind(this);
    this.setCameraAsContentModalIsOpen = this.setCameraAsContentModalIsOpen.bind(this);
    this.setPropsToPassModal = this.setPropsToPassModal.bind(this);
    this.setForceOpen = this.setForceOpen.bind(this);
    this.handleTimerClick = this.handleTimerClick.bind(this);
  }

  componentDidUpdate(prevProps) {
    const { amIPresenter: wasPresenter } = prevProps;
    const { amIPresenter: isPresenter } = this.props;
    if (wasPresenter && !isPresenter) {
      this.setExternalVideoModalIsOpen(false);
    }
  }

  handleExternalVideoClick() {
    this.setExternalVideoModalIsOpen(true);
  }

  handleTimerClick() {
    const { isTimerActive, layoutContextDispatch } = this.props;
    if (!isTimerActive) {
      TimerService.activateTimer(layoutContextDispatch);
    } else {
      TimerService.deactivateTimer();
    }
  }

  getAvailableActions() {
    const {
      intl,
      amIPresenter,
      allowExternalVideo,
      handleTakePresenter,
      isSharingVideo,
      isPollingEnabled,
      isSelectRandomUserEnabled,
      stopExternalVideoShare,
      isTimerActive,
      isTimerEnabled,
      layoutContextDispatch,
      setMeetingLayout,
      setPushLayout,
      showPushLayout,
      amIModerator,
      isMobile,
      hasCameraAsContent,
      isCameraAsContentEnabled,
      isTimerFeatureEnabled,
    } = this.props;

    const { pollBtnLabel, presentationLabel, takePresenter } = intlMessages;

    const { formatMessage } = intl;

    const actions = [];

    if (amIPresenter && isPresentationEnabled()) {
      actions.push({
        icon: 'upload',
        dataTest: 'managePresentations',
        label: formatMessage(presentationLabel),
        key: this.presentationItemId,
        onClick: handlePresentationClick,
        dividerTop: this.props?.presentations?.length > 1 ? true : false,
      });
    }

    if (amIPresenter && isPollingEnabled) {
      actions.push({
        icon: 'polling',
        dataTest: 'polling',
        label: formatMessage(pollBtnLabel),
        key: this.pollId,
        onClick: () => {
          if (Session.equals('pollInitiated', true)) {
            Session.set('resetPollPanel', true);
          }
          layoutContextDispatch({
            type: ACTIONS.SET_SIDEBAR_CONTENT_IS_OPEN,
            value: true,
          });
          layoutContextDispatch({
            type: ACTIONS.SET_SIDEBAR_CONTENT_PANEL,
            value: PANELS.POLL,
          });
          Session.set('forcePollOpen', true);
        },
      });
    }

    if (!amIPresenter && amIModerator) {
      actions.push({
        icon: 'presentation',
        label: formatMessage(takePresenter),
        key: this.takePresenterId,
        onClick: () => handleTakePresenter(),
      });
    }

    if (amIPresenter && allowExternalVideo) {
      actions.push({
        icon: !isSharingVideo ? 'external-video' : 'external-video_off',
        label: !isSharingVideo
          ? intl.formatMessage(intlMessages.startExternalVideoLabel)
          : intl.formatMessage(intlMessages.stopExternalVideoLabel),
        key: 'external-video',
        onClick: isSharingVideo ? stopExternalVideoShare : this.handleExternalVideoClick,
        dataTest: 'shareExternalVideo',
      });
    }

    if (amIPresenter && isSelectRandomUserEnabled) {
      actions.push({
        icon: 'user',
        label: intl.formatMessage(intlMessages.selectRandUserLabel),
        key: this.selectUserRandId,
        onClick: () => this.setRandomUserSelectModalIsOpen(true),
        dataTest: 'selectRandomUser',
      });
    }

    if (amIModerator && isTimerEnabled && isTimerFeatureEnabled) {
      actions.push({
        icon: 'time',
        label: isTimerActive
          ? intl.formatMessage(intlMessages.deactivateTimerStopwatchLabel)
          : intl.formatMessage(intlMessages.activateTimerStopwatchLabel),
        key: this.timerId,
        onClick: () => this.handleTimerClick(),
      });
    }

    if (isLayoutsEnabled()) {
      actions.push({
        icon: 'manage_layout',
        label: intl.formatMessage(intlMessages.layoutModal),
        key: 'layoutModal',
        onClick: () => this.setLayoutModalIsOpen(true),
        dataTest: 'manageLayoutBtn',
      });
    }

    if (isCameraAsContentEnabled && amIPresenter && !isMobile) {
      actions.push({
        icon: hasCameraAsContent ? 'video_off' : 'video',
        label: hasCameraAsContent
          ? intl.formatMessage(intlMessages.unshareCameraAsContent)
          : intl.formatMessage(intlMessages.shareCameraAsContent),
        key: 'camera as content',
        onClick: hasCameraAsContent
          ? screenshareHasEnded
          : () => {
              screenshareHasEnded();
              this.setCameraAsContentModalIsOpen(true);
            },
        dataTest: 'shareCameraAsContent',
      });
    }

    return actions;
  }

  makePresentationItems() {
    const { presentations, setPresentation, podIds } = this.props;

    if (!podIds || podIds.length < 1) return [];

    // We still have code for other pods from the Flash client. This intentionally only cares
    // about the first one because it's the default.
    const { podId } = podIds[0];

    const presentationItemElements = presentations
      .sort((a, b) => a.name.localeCompare(b.name))
      .map((p) => {
        const customStyles = { color: colorPrimary };

        return {
          customStyles: p.current ? customStyles : null,
          icon: 'file',
          iconRight: p.current ? 'check' : null,
          selected: p.current ? true : false,
          label: p.name,
          description: 'uploaded presentation file',
          key: `uploaded-presentation-${p.id}`,
          onClick: () => {
            setPresentation(p.id, podId);
          },
        };
      });
    return presentationItemElements;
  }

  setExternalVideoModalIsOpen(value) {
    this.setState({ isExternalVideoModalOpen: value });
  }

  setRandomUserSelectModalIsOpen(value) {
    this.setState({ isRandomUserSelectModalOpen: value });
  }

  setLayoutModalIsOpen(value) {
    this.setState({ isLayoutModalOpen: value });
  }

  setCameraAsContentModalIsOpen(value) {
    this.setState({ isCameraAsContentModalOpen: value });
  }

  setPropsToPassModal(value) {
    this.setState({ propsToPassModal: value });
  }
  setForceOpen(value) {
    this.setState({ forceOpen: value });
  }

  renderModal(isOpen, setIsOpen, priority, Component) {
    return isOpen ? (
      <Component
        {...{
          onRequestClose: () => setIsOpen(false),
          priority,
          setIsOpen,
          isOpen,
        }}
      />
    ) : null;
  }

  render() {
    const {
      intl,
      amIPresenter,
      shortcuts: OPEN_ACTIONS_AK,
      isMeteorConnected,
      isDropdownOpen,
      isMobile,
      isRTL,
      isSelectRandomUserEnabled,
      propsToPassModal,
    } = this.props;

    const {
      isExternalVideoModalOpen,
      isRandomUserSelectModalOpen,
      isLayoutModalOpen,
      isCameraAsContentModalOpen,
    } = this.state;

    const availableActions = this.getAvailableActions();
    const availablePresentations = this.makePresentationItems();
    const children = availablePresentations.length > 1 && amIPresenter
      ? availablePresentations.concat(availableActions)
      : availableActions;

    const customStyles = { top: '-1rem' };

    if (availableActions.length === 0 || !isMeteorConnected) {
      return null;
    }

    return (
      <>
        <BBBMenu
          customStyles={!isMobile ? customStyles : null}
          accessKey={OPEN_ACTIONS_AK}
          trigger={(
            <Styled.HideDropdownButton
              open={isDropdownOpen}
              hideLabel
              aria-label={intl.formatMessage(intlMessages.actionsLabel)}
              data-test="actionsButton"
              label={intl.formatMessage(intlMessages.actionsLabel)}
              icon="plus"
              color="primary"
              size="lg"
              circle
              onClick={() => null}
            />
          )}
          actions={children}
          opts={{
            id: 'actions-dropdown-menu',
            keepMounted: true,
            transitionDuration: 0,
            elevation: 3,
            getcontentanchorel: null,
            fullwidth: 'true',
            anchorOrigin: { vertical: 'top', horizontal: isRTL ? 'right' : 'left' },
            transformOrigin: { vertical: 'bottom', horizontal: isRTL ? 'right' : 'left' },
          }}
        />
        {this.renderModal(
          isExternalVideoModalOpen,
          this.setExternalVideoModalIsOpen,
          'low',
          ExternalVideoModal,
        )}
        {amIPresenter && isSelectRandomUserEnabled
          ? this.renderModal(
            isRandomUserSelectModalOpen,
            this.setRandomUserSelectModalIsOpen,
            'low',
            RandomUserSelectContainer,
          )
          : null}
        {this.renderModal(
          isLayoutModalOpen,
          this.setLayoutModalIsOpen,
          'low',
          LayoutModalContainer,
        )}
        {this.renderModal(
          isCameraAsContentModalOpen,
          this.setCameraAsContentModalIsOpen,
          'low',
          () => (
            <VideoPreviewContainer
              cameraAsContent
              amIPresenter
              {...{
                callbackToClose: () => {
                  this.setPropsToPassModal({});
                  this.setForceOpen(false);
                },
                priority: 'low',
                setIsOpen: this.setCameraAsContentModalIsOpen,
                isOpen: isCameraAsContentModalOpen,
              }}
              {...propsToPassModal}
            />
          )
        )}
      </>
    );
  }
}

ActionsDropdown.propTypes = propTypes;
ActionsDropdown.defaultProps = defaultProps;

export default withShortcutHelper(ActionsDropdown, 'openActions');
