/* @flow */

import type { Dispatch } from 'redux';

import { appNavigate } from '../app';
import { MEDIA_TYPE } from '../base/media';
import { isLocalTrackMuted } from '../base/tracks';

/**
 * Maps redux actions to {@link Toolbox} (React {@code Component}) props.
 *
 * @param {Function} dispatch - The redux {@code dispatch} function.
 * @returns {{
 *     _onHangup: Function,
 *     _onToggleAudio: Function,
 *     _onToggleVideo: Function
 * }}
 * @private
 */
export function abstractMapDispatchToProps(dispatch: Dispatch<*>): Object {
    return {
        // Inject {@code dispatch} into the React Component's props in case it
        // needs to dispatch an action in the redux store without
        // {@code mapDispatchToProps}.
        dispatch,

        /**
         * Dispatches action to leave the current conference.
         *
         * @private
         * @returns {void}
         * @type {Function}
         */
        _onHangup() {
            // XXX We don't know here which value is effectively/internally
            // used when there's no valid room name to join. It isn't our
            // business to know that anyway. The undefined value is our
            // expression of (1) the lack of knowledge & (2) the desire to no
            // longer have a valid room name to join.
            dispatch(appNavigate(undefined));
        }
    };
}

/**
 * Maps parts of the redux state to {@link Toolbox} (React {@code Component})
 * props.
 *
 * @param {Object} state - The redux state of which parts are to be mapped to
 * {@code Toolbox} props.
 * @protected
 * @returns {{
 *     _audioMuted: boolean,
 *     _videoMuted: boolean,
 *     _visible: boolean
 * }}
 */
export function abstractMapStateToProps(state: Object): Object {
    const tracks = state['features/base/tracks'];
    const { visible } = state['features/toolbox'];

    return {
        /**
         * Flag showing whether audio is muted.
         *
         * @protected
         * @type {boolean}
         */
        _audioMuted: isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO),

        /**
         * Flag showing whether video is muted.
         *
         * @protected
         * @type {boolean}
         */
        _videoMuted: isLocalTrackMuted(tracks, MEDIA_TYPE.VIDEO),

        /**
         * Flag showing whether toolbox is visible.
         *
         * @protected
         * @type {boolean}
         */
        _visible: visible
    };
}

/**
 * Returns the button object corresponding to a specific {@code buttonName}.
 *
 * @param {string} buttonName - The name of the button.
 * @param {Object} state - The current state.
 * @returns {Object} - The button object.
 */
export function getButton(buttonName: string, state: Object) {
    const { primaryToolbarButtons, secondaryToolbarButtons }
        = state['features/toolbox'];

    return primaryToolbarButtons.get(buttonName)
        || secondaryToolbarButtons.get(buttonName);
}
