import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { connect } from 'react-redux';
import { prefetch } from '../../../mobile/image-cache';
import { translate } from '../../i18n';
import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
import {
    MEDIA_TYPE,
    shouldRenderVideoTrack,
    VideoTrack
} from '../../media';
import { Container, TintedView } from '../../react';
import { getTrackByMediaTypeAndParticipant } from '../../tracks';
import {
    getAvatarURL, getParticipantById, getParticipantDisplayName
} from '../functions';
import Avatar from './Avatar';
import styles from './styles';
/**
 * Implements a React Component which depicts a specific participant's avatar
 * and video.
 *
 * @extends Component
 */
class ParticipantView extends Component {
    /**
     * ParticipantView component's property types.
     *
     * @static
     */
    static propTypes = {
        /**
         * The indicator which determines whether conferencing is in audio-only
         * mode.
         *
         * @private
         */
        _audioOnly: PropTypes.bool,
        /**
         * The source (e.g. URI, URL) of the avatar image of the participant
         * with {@link #participantId}.
         *
         * @private
         */
        _avatar: PropTypes.string,
        /**
         * The connection status of the participant. Her video will only be
         * rendered if the connection status is 'active'; otherwise, the avatar
         * will be rendered. If undefined, 'active' is presumed.
         *
         * @private
         */
        _connectionStatus: PropTypes.string,
        /**
         * The name of the participant which this component represents.
         *
         * @private
         */
        _participantName: PropTypes.string,
        /**
         * The video Track of the participant with {@link #participantId}.
         */
        _videoTrack: PropTypes.object,
        /**
         * The style, if any, of the avatar in addition to the default style.
         */
        avatarStyle: PropTypes.object,
        /**
         * The ID of the participant (to be) depicted by ParticipantView.
         *
         * @public
         */
        participantId: PropTypes.string,
        /**
         * True if the avatar of the depicted participant is to be shown should
         * the avatar be available and the video of the participant is not to be
         * shown; otherwise, false. If undefined, defaults to true.
         */
        showAvatar: PropTypes.bool,
        /**
         * True if the video of the depicted participant is to be shown should
         * the video be available. If undefined, defaults to true.
         */
        showVideo: PropTypes.bool,
        /**
         * The style, if any, to apply to ParticipantView in addition to its
         * default style.
         */
        style: PropTypes.object,
        /**
         * The function to translate human-readable text.
         */
        t: PropTypes.func,
        /**
         * Indicates if the connectivity info label should be shown, if
         * appropriate. It will be shown in case the connection is interrupted.
         */
        useConnectivityInfoLabel: PropTypes.bool,
        /**
         * The z-order of the Video of ParticipantView in the stacking space of
         * all Videos. For more details, refer to the zOrder property of the
         * Video class for React Native.
         */
        zOrder: PropTypes.number
    };
    /**
     * Renders the connection status label, if appropriate.
     *
     * @param {string} connectionStatus - The status of the participant's
     * connection.
     * @private
     * @returns {ReactElement|null}
     */
    _renderConnectionInfo(connectionStatus) {
        let messageKey;
        switch (connectionStatus) {
        case JitsiParticipantConnectionStatus.INACTIVE:
            messageKey = 'connection.LOW_BANDWIDTH';
            break;
        case JitsiParticipantConnectionStatus.INTERRUPTED:
            messageKey = 'connection.USER_CONNECTION_INTERRUPTED';
            break;
        default:
            return null;
        }
        const {
            avatarStyle,
            _participantName: displayName,
            t
        } = this.props;
        // XXX Consider splitting this component into 2: one for the large
        // view and one for the thumbnail. Some of these don't apply to both.
        const containerStyle = {
            ...styles.connectionInfoContainer,
            width: avatarStyle.width * 1.5
        };
        return (
            
                
                    { t(messageKey, { displayName }) }
                
            
        );
    }
    /**
     * Implements React's {@link Component#render()}.
     *
     * @inheritdoc
     * @returns {ReactElement}
     */
    render() {
        const {
            _avatar: avatar,
            _connectionStatus: connectionStatus,
            _videoTrack: videoTrack
        } = this.props;
        // Is the video to be rendered?
        // FIXME It's currently impossible to have true as the value of
        // waitForVideoStarted because videoTrack's state videoStarted will be
        // updated only after videoTrack is rendered.
        // XXX Note that, unlike on web, we don't render video when the
        // connection status is interrupted, this is because the renderer
        // doesn't retain the last frame forever, so we would end up with a
        // black screen.
        const waitForVideoStarted = false;
        const renderVideo
            = !this.props._audioOnly
                && (connectionStatus
                    === JitsiParticipantConnectionStatus.ACTIVE)
                && shouldRenderVideoTrack(videoTrack, waitForVideoStarted);
        // Is the avatar to be rendered?
        const renderAvatar = Boolean(!renderVideo && avatar);
        // If the connection has problems we will "tint" the video / avatar.
        const useTint
            = connectionStatus === JitsiParticipantConnectionStatus.INACTIVE
                || connectionStatus
                    === JitsiParticipantConnectionStatus.INTERRUPTED;
        return (
            
                { renderVideo
                    // The consumer of this ParticipantView is allowed to forbid
                    // showing the video if the private logic of this
                    // ParticipantView determines that the video could be
                    // rendered.
                    && _toBoolean(this.props.showVideo, true)
                    &&  }
                { renderAvatar
                    // The consumer of this ParticipantView is allowed to forbid
                    // showing the avatar if the private logic of this
                    // ParticipantView determines that the avatar could be
                    // rendered.
                    && _toBoolean(this.props.showAvatar, true)
                    &&  }
                { useTint
                    // If the connection has problems, tint the video / avatar.
                    &&  }
                { this.props.useConnectivityInfoLabel
                    && this._renderConnectionInfo(connectionStatus) }
            
        );
    }
}
/**
 * Converts the specified value to a boolean value. If the specified value is
 * undefined, returns the boolean value of undefinedValue.
 *
 * @param {any} value - The value to convert to a boolean value should it not be
 * undefined.
 * @param {any} undefinedValue - The value to convert to a boolean value should
 * the specified value be undefined.
 * @private
 * @returns {boolean}
 */
function _toBoolean(value, undefinedValue) {
    return Boolean(typeof value === 'undefined' ? undefinedValue : value);
}
/**
 * Maps (parts of) the Redux state to the associated ParticipantView's props.
 *
 * @param {Object} state - The Redux state.
 * @param {Object} ownProps - The React Component props passed to the associated
 * (instance of) ParticipantView.
 * @private
 * @returns {{
 *     _audioOnly: boolean,
 *     _avatar: string,
 *     _connectionStatus: string,
 *     _videoTrack: Track
 * }}
 */
function _mapStateToProps(state, ownProps) {
    const { participantId } = ownProps;
    const participant
        = getParticipantById(
            state['features/base/participants'],
            participantId);
    let avatar;
    let connectionStatus;
    let participantName;
    if (participant) {
        avatar = getAvatarURL(participant);
        connectionStatus = participant.connectionStatus;
        participantName = getParticipantDisplayName(state);
        // Avatar (on React Native) now has the ability to generate an
        // automatically-colored default image when no URI/URL is specified or
        // when it fails to load. In order to make the coloring permanent(ish)
        // per participant, Avatar will need something permanent(ish) per
        // perticipant, obviously. A participant's ID is such a piece of data.
        // But the local participant changes her ID as she joins, leaves.
        // TODO @lyubomir: The participants may change their avatar URLs at
        // runtime which means that, if their old and new avatar URLs fail to
        // download, Avatar will change their automatically-generated colors.
        avatar || participant.local || (avatar = `#${participant.id}`);
        // ParticipantView knows before Avatar that an avatar URL will be used
        // so it's advisable to prefetch here.
        avatar && prefetch({ uri: avatar });
    }
    return {
        _audioOnly: state['features/base/conference'].audioOnly,
        _avatar: avatar,
        _connectionStatus:
            connectionStatus
                || JitsiParticipantConnectionStatus.ACTIVE,
        _participantName: participantName,
        _videoTrack:
            getTrackByMediaTypeAndParticipant(
                state['features/base/tracks'],
                MEDIA_TYPE.VIDEO,
                participantId)
    };
}
export default translate(connect(_mapStateToProps)(ParticipantView));