/* @flow */

import { CONFERENCE_LEFT } from '../conference';
import { MiddlewareRegistry } from '../redux';
import { setTrackMuted, TRACK_ADDED } from '../tracks';

import {
    setAudioMuted,
    setCameraFacingMode,
    setVideoMuted
} from './actions';
import { CAMERA_FACING_MODE } from './constants';

/**
 * Middleware that captures CONFERENCE_LEFT action and restores initial state
 * for media devices. Also captures TRACK_ADDED to sync 'muted' state.
 *
 * @param {Store} store - Redux store.
 * @returns {Function}
 */
MiddlewareRegistry.register(store => next => action => {
    const result = next(action);

    switch (action.type) {
    case CONFERENCE_LEFT:
        _resetInitialMediaState(store);
        break;

    case TRACK_ADDED:
        action.track.local && _syncTrackMutedState(store, action.track);
        break;
    }

    return result;
});

/**
 * Resets initial media state.
 *
 * @param {Store} store - Redux store.
 * @private
 * @returns {void}
 */
function _resetInitialMediaState(store) {
    const { dispatch, getState } = store;
    const state = getState()['features/base/media'];

    state.audio.muted && dispatch(setAudioMuted(false));
    (state.video.facingMode !== CAMERA_FACING_MODE.USER)
        && dispatch(setCameraFacingMode(CAMERA_FACING_MODE.USER));
    state.video.muted && dispatch(setVideoMuted(false));
}

/**
 * Syncs muted state of local media track with muted state from media state.
 *
 * @param {Store} store - Redux store.
 * @param {Track} track - Local media track.
 * @private
 * @returns {void}
 */
function _syncTrackMutedState(store, track) {
    const state = store.getState()['features/base/media'];
    const muted = state[track.mediaType].muted;

    // XXX If muted state of track when it was added is different from our media
    // muted state, we need to mute track and explicitly modify 'muted' property
    // on track. This is because though TRACK_ADDED action was dispatched it's
    // not yet in Redux state and JitsiTrackEvents.TRACK_MUTE_CHANGED may be
    // fired before track gets to state.
    if (track.muted !== muted) {
        track.muted = muted;
        setTrackMuted(track.jitsiTrack, muted);
    }
}
