'use strict';
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import _ from 'lodash';
import { Icon } from '../Icon';
import { showAlert } from '../utils';
import EventBus from '../../utils/EventBus';
import { formatSeconds, getProcessedPercentage, KEY_CODE } from './utils';
import { FocusHelper } from '../../utils/FocusHelper';
import { VolumeControl } from './VolumeControl';
import { Button } from '../Button';
import lang from '../../../lang/common/index-en_US';
var MODES = {
    FULL: 0,
    INVISIBLE: 1
};
var PLAYING_EVENT = 'AUDIO_PLAYING';
var PROGRESS_BAR = 'audio-progress-bar';
var PROGRESS_INDICATOR = 'audio-progress-current-pos';
var STEP = 1; //1 second
var AudioPlayer = /** @class */ (function (_super) {
    __extends(AudioPlayer, _super);
    function AudioPlayer(props, params) {
        var _this = _super.call(this, props, params) || this;
        _this.stopPlayer = function (instance) {
            if (instance !== _this && _this.player) {
                //other players are playing
                _this.player.pause();
                _this.stopMonitorAudioProgress();
                _this.setState({
                    playing: false
                });
            }
        };
        _this.progressDrag = function (e) {
            e.stopPropagation();
            e.preventDefault();
            _this.updateProgressByMouse(e, false);
        };
        _this.progressDragStart = function (e) {
            e.stopPropagation();
            e.preventDefault();
            _this.draggingProgress = true;
            _this.stopMonitorAudioProgress();
            window.addEventListener('mousemove', _this.progressDrag);
        };
        _this.windowDragEnd = function (e) {
            if (_this.draggingProgress) {
                window.removeEventListener('mousemove', _this.progressDrag);
                _this.updateProgressByMouse(e, true);
                _this.draggingProgress = false;
            }
        };
        _this.progressKeyDown = function (e) {
            var isValidKey = false;
            switch (e.keyCode) {
                case KEY_CODE.RIGHT:
                case KEY_CODE.UP:
                    isValidKey = true;
                    _this.updateProgressByKeyboard(e, false, STEP);
                    break;
                case KEY_CODE.LEFT:
                case KEY_CODE.DOWN:
                    isValidKey = true;
                    _this.updateProgressByKeyboard(e, false, -STEP);
                    break;
                case KEY_CODE.PAGEUP:
                    isValidKey = true;
                    _this.updateProgressByKeyboard(e, false, STEP * 10);
                    break;
                case KEY_CODE.PAGEDOWN:
                    isValidKey = true;
                    _this.updateProgressByKeyboard(e, false, -STEP * 10);
                    break;
                case KEY_CODE.END:
                    isValidKey = true;
                    _this.updateProgressByKeyboard(e, false, _this.state.duration || 60);
                    break;
                case KEY_CODE.HOME:
                    isValidKey = true;
                    _this.updateProgressByKeyboard(e, false, -_this.state.duration || -60);
                    break;
            }
            if (isValidKey) {
                e.stopPropagation();
                e.preventDefault();
            }
        };
        _this.progressKeyUp = function (e) {
            var isValidKey = _.find(KEY_CODE, function (value) {
                return value === e.keyCode;
            });
            if (isValidKey) {
                e.stopPropagation();
                e.preventDefault();
                _this.updateProgressByKeyboard(e, true, 0);
            }
        };
        _this.setVolume = function (currentVolume, isMuted) {
            var volume = _this.state.volume;
            if (_.isUndefined(isMuted)) {
                if (!currentVolume) {
                    currentVolume = volume;
                    isMuted = true;
                }
                else {
                    isMuted = false;
                }
            }
            if (_this.player) {
                _this.player.volume = isMuted ? 0 : currentVolume;
            }
            _this.setState({
                volume: currentVolume,
                isMuted: isMuted
            });
        };
        _this.onPlayerBlur = function (event) {
            var audioPlayerBlurred = !_this.audioPlayerWrapper.contains(event.relatedTarget);
            if (audioPlayerBlurred && _this.props.onBlur) {
                _this.props.onBlur(event);
            }
        };
        _this.state = {
            playing: false,
            currentTime: 0,
            progressIndicatorPos: 0,
            duration: 0,
            volume: 1,
            isMuted: false
        };
        _this.focusHelper = new FocusHelper();
        return _this;
    }
    AudioPlayer.prototype.componentWillMount = function () {
        EventBus.on(PLAYING_EVENT, this.stopPlayer);
        if (this.props.autoplay) {
            this.play();
        }
    };
    AudioPlayer.prototype.componentDidMount = function () {
        var _this = this;
        if (!this.initialized && !this.isInVisible()) {
            var progressBar = this.refs[PROGRESS_BAR];
            var progressIndicator = this.refs[PROGRESS_INDICATOR];
            this.progressIndicatorWidth = progressIndicator.offsetWidth;
            // Drag start
            progressBar.addEventListener('mousedown', this.progressDragStart);
            // Drag end
            window.addEventListener('mouseup', this.windowDragEnd);
            // Drag end
            progressIndicator.addEventListener('keydown', this.progressKeyDown);
            //Key up
            progressIndicator.addEventListener('keyup', this.progressKeyUp);
        }
        this.initialized = true;
        if (this.props.autoFocus) {
            this.lastFocusElement = document.activeElement;
            setTimeout(function () { return _this.focusHelper.focus(); });
        }
    };
    AudioPlayer.prototype.componentWillReceiveProps = function (nextProps) {
        if (this.player &&
            (this.props.audioUrl !== nextProps.audioUrl || this.props.id !== nextProps.id)) {
            this.player.pause();
            this.stopMonitorAudioProgress();
            this.player.src = nextProps.audioUrl.replace('.wav', '.mp3');
            this.player.volume = 1;
            this.setState({
                playing: false,
                currentTime: 0,
                progressIndicatorPos: 0,
                duration: 0,
                volume: 1,
                isMuted: false
            });
            if (nextProps.autoplay) {
                this.play(true);
            }
        }
    };
    AudioPlayer.prototype.componentWillUnmount = function () {
        if (this.player) {
            this.player.pause();
            this.player.onerror = null;
            this.stopMonitorAudioProgress();
            delete this.player;
        }
        if (this.initialized && !this.isInVisible()) {
            var progressIndicator = this.refs[PROGRESS_INDICATOR];
            progressIndicator.removeEventListener('keydown', this.progressKeyDown);
            progressIndicator.removeEventListener('keyup', this.progressKeyUp);
            window.removeEventListener('mouseup', this.windowDragEnd);
            window.removeEventListener('mousedown', this.progressDragStart);
            window.removeEventListener('mousemove', this.progressDrag);
        }
        EventBus.off(PLAYING_EVENT, this.stopPlayer);
        if (this.lastFocusElement) {
            this.lastFocusElement.focus();
        }
    };
    AudioPlayer.prototype.getPlayButton = function () {
        var _this = this;
        if (this.isInVisible()) {
            return null;
        }
        var playing = this.state.playing;
        return (React.createElement(Button, { className: "rc-audio-icon-wrapper", testAutomationId: "audioPlay" + this.props.id, ref: this.focusHelper.setEl, onClick: function () {
                _this.play();
            }, "aria-pressed": playing, "aria-label": playing ? this.props.pauseLabel : this.props.playLabel },
            React.createElement(Icon, { name: playing ? 'pause' : 'play' })));
    };
    AudioPlayer.prototype.getProgressBar = function () {
        if (!this.isFullMode()) {
            return null;
        }
        var _a = this.state, progressIndicatorPos = _a.progressIndicatorPos, duration = _a.duration, currentTime = _a.currentTime;
        var progressIndicatorPercent = progressIndicatorPos * 100;
        var percent = progressIndicatorPercent + '%';
        var id = this.props.id;
        var indicatorStyle = {};
        var ariaValueNow;
        if (this.initialized) {
            indicatorStyle.left = percent;
            if (progressIndicatorPos >
                1 - this.progressIndicatorWidth / this.refs[PROGRESS_BAR].offsetWidth) {
                indicatorStyle.left = '100%';
                progressIndicatorPercent = 100;
                indicatorStyle.WebkitTransform = 'translateX(-100%)';
                indicatorStyle.transform = indicatorStyle.WebkitTransform;
            }
            ariaValueNow = Math.round(progressIndicatorPercent);
        }
        else {
            ariaValueNow = 0;
        }
        return (React.createElement("div", { ref: PROGRESS_BAR, className: "audio-process-bar " + PROGRESS_BAR, "data-test-automation-id": "audioProgress" + this.props.id },
            React.createElement("div", { className: "audio-process-bar-total", "data-test-automation-id": "audioProgressTotal" + id }),
            React.createElement("div", { className: "audio-process-bar-left", style: { width: percent }, "data-test-automation-id": "audioProgressLeft" + id }),
            React.createElement("div", { role: "slider", tabIndex: 0, "aria-label": this.props.timeSlider, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": ariaValueNow, "aria-valuetext": duration && !_.isNaN(duration)
                    ? formatSeconds(currentTime)
                    : ariaValueNow + '%', ref: PROGRESS_INDICATOR, className: "audio-process-indicator", style: indicatorStyle, "data-test-automation-id": "audioProgressIndicator" + id })));
    };
    AudioPlayer.prototype.getDuration = function () {
        if (!this.isFullMode()) {
            return null;
        }
        var _a = this.state, currentTime = _a.currentTime, duration = _a.duration;
        return (React.createElement("div", { className: "audio-duration", "data-test-automation-id": "audioDuration" + this.props.id },
            formatSeconds(currentTime),
            "\u00A0/\u00A0",
            formatSeconds(duration)));
    };
    AudioPlayer.prototype.getVolumnControl = function () {
        if (!this.isFullMode()) {
            return null;
        }
        var id = this.props.id;
        var _a = this.state, volume = _a.volume, isMuted = _a.isMuted;
        return (React.createElement(VolumeControl, { id: id, volume: volume, isMuted: isMuted, setVolume: this.setVolume }));
    };
    AudioPlayer.prototype.getRecordButton = function () {
        if (this.isInVisible()) {
            return null;
        }
        var _a = this.props, onRecord = _a.onRecord, id = _a.id;
        if (!onRecord || !_.isFunction(onRecord)) {
            return null;
        }
        return (React.createElement(Button, { "aria-label": this.props.recordLabel, className: "rc-audio-icon-wrapper rc-audio-record", testAutomationId: "audioRecord" + id, onClick: function (e) {
                e.preventDefault();
                onRecord();
            } },
            React.createElement(Icon, { name: "record", "aria-hidden": "true" })));
    };
    AudioPlayer.prototype.getDownloadBtn = function () {
        if (this.isInVisible()) {
            return null;
        }
        var downloadUrl = this.props.downloadUrl;
        return downloadUrl ? (React.createElement("div", { className: "rc-audio-download" },
            React.createElement("a", { role: "button", "aria-label": this.props.downloadLabel, "data-test-automation-id": "audioDownload" + this.props.id, href: downloadUrl, target: "_blank" },
                React.createElement(Icon, { name: "circle-download" })))) : null;
    };
    AudioPlayer.prototype.play = function (forcePlay) {
        if (forcePlay === void 0) { forcePlay = false; }
        if (!this.props.audioUrl) {
            return;
        }
        var playing = this.state.playing;
        if (forcePlay) {
            playing = false;
        }
        this.player = this.player || this.createAudio();
        this.player.volume = this.state.isMuted ? 0 : this.state.volume;
        var canPause = this.props.canPause;
        if (!playing) {
            this.player.play();
        }
        else if (!!canPause) {
            this.player.pause();
        }
        this.monitorAudioProgress();
        var duration = this.player.duration;
        if (!duration || _.isNaN(duration)) {
            duration = 0;
        }
        this.setState({
            playing: !playing,
            currentTime: this.player.currentTime,
            duration: duration
        });
    };
    AudioPlayer.prototype.monitorAudioProgress = function () {
        var _this = this;
        if (this.player && !this.player.ontimeupdate) {
            this.player.ontimeupdate = function () {
                var _a = _this.player, currentTime = _a.currentTime, duration = _a.duration;
                _this.setState({
                    currentTime: currentTime,
                    progressIndicatorPos: duration > 0 ? currentTime / duration : 0
                });
            };
        }
    };
    AudioPlayer.prototype.stopMonitorAudioProgress = function () {
        if (this.player && this.player.ontimeupdate) {
            this.player.ontimeupdate = null;
        }
    };
    AudioPlayer.prototype.createAudio = function () {
        var _this = this;
        var audio = new Audio(this.props.audioUrl.replace('.wav', '.mp3'));
        var onPlay = this.props.onPlay;
        audio.onended = function () {
            var progressIndicatorPos = _this.state.progressIndicatorPos;
            if (_this.player.ontimeupdate) {
                progressIndicatorPos = 0;
            }
            _this.setState({
                currentTime: 0,
                progressIndicatorPos: progressIndicatorPos,
                playing: false
            });
        };
        audio.onloadeddata = function () {
            _this.setState({
                duration: _this.player.duration
            });
        };
        audio.onerror = function () {
            var _a = _this.props, onLoadError = _a.onLoadError, loadingError = _a.loadingError;
            if (onLoadError) {
                onLoadError(loadingError);
            }
            else {
                showAlert(loadingError);
            }
        };
        audio.onplay = function () {
            EventBus.emit(PLAYING_EVENT, _this);
            if (onPlay) {
                onPlay();
            }
        };
        return audio;
    };
    AudioPlayer.prototype.updateProgressByMouse = function (e, play) {
        if (play === void 0) { play = true; }
        var progressBar = this.refs[PROGRESS_BAR];
        var distance = e.clientX - progressBar.getBoundingClientRect().left;
        var processPercentage = getProcessedPercentage(distance, progressBar.offsetWidth, this.progressIndicatorWidth / 2);
        this.updateProgress(processPercentage, play);
    };
    AudioPlayer.prototype.updateProgressByKeyboard = function (e, play, step) {
        if (play === void 0) { play = true; }
        if (step === void 0) { step = STEP; }
        var duration = this.state.duration || 60; //if the audio wasn't loaded, pretend it's 1 minutes long
        var progressBar = this.refs[PROGRESS_BAR];
        var progressIndicator = this.refs[PROGRESS_INDICATOR];
        var positionStep = (step / duration) * progressBar.offsetWidth;
        var originalPosition = progressIndicator.getBoundingClientRect().left -
            progressBar.getBoundingClientRect().left;
        var distance = originalPosition +
            positionStep +
            (this.progressIndicatorWidth / 2) * (step < 0 ? -1 : 1);
        var processPercentage = play
            ? this.state.progressIndicatorPos
            : getProcessedPercentage(distance, progressBar.offsetWidth, this.progressIndicatorWidth / 2);
        this.stopMonitorAudioProgress();
        this.updateProgress(processPercentage, play);
    };
    AudioPlayer.prototype.updateProgress = function (processPercentage, play) {
        if (play === void 0) { play = true; }
        var _a = this.state, currentTime = _a.currentTime, duration = _a.duration, progressIndicatorPos = _a.progressIndicatorPos;
        if (duration === 0) {
            //audio not loaded
            if (progressIndicatorPos !== processPercentage) {
                this.setState({
                    progressIndicatorPos: processPercentage
                });
            }
        }
        else {
            currentTime = duration * processPercentage;
            if (currentTime === duration) {
                currentTime = duration - 0.01;
            }
            if (play) {
                this.player.currentTime = currentTime;
                this.player.play();
                this.monitorAudioProgress();
                this.setState({
                    currentTime: currentTime,
                    progressIndicatorPos: processPercentage,
                    playing: true
                });
            }
            else {
                this.setState({
                    progressIndicatorPos: processPercentage
                });
            }
        }
    };
    AudioPlayer.prototype.isFullMode = function () {
        return this.props.mode === MODES.FULL;
    };
    AudioPlayer.prototype.isInVisible = function () {
        return this.props.mode === MODES.INVISIBLE;
    };
    AudioPlayer.prototype.render = function () {
        var _this = this;
        var _a = this.props, id = _a.id, mode = _a.mode, onRecord = _a.onRecord;
        var audioClassName = classnames('rc-audio', {
            'rc-audio-invisible': mode === MODES.INVISIBLE
        });
        var className = classnames('rc-audio-player', {
            'rc-audio-player-full': mode === MODES.FULL,
            'rc-audio-player-recorder': !!onRecord
        });
        return (React.createElement("div", { id: id, className: audioClassName, onBlur: this.onPlayerBlur, ref: function (ref) { return (_this.audioPlayerWrapper = ref); } },
            React.createElement("div", { className: className, "data-test-automation-id": "audioPlayer" + id },
                this.getPlayButton(),
                this.getProgressBar(),
                this.getDuration(),
                this.getVolumnControl()),
            this.getRecordButton(),
            this.getDownloadBtn()));
    };
    AudioPlayer.MODES = MODES;
    AudioPlayer.propTypes = {
        id: PropTypes.string,
        mode: PropTypes.number,
        audioUrl: PropTypes.string,
        autoplay: PropTypes.bool,
        canPause: PropTypes.bool,
        onPlay: PropTypes.func,
        onRecord: PropTypes.func,
        downloadUrl: PropTypes.string,
        loadingError: PropTypes.string,
        onLoadError: PropTypes.func,
        pauseLabel: PropTypes.string,
        playLabel: PropTypes.string,
        timeSlider: PropTypes.string,
        recordLabel: PropTypes.string,
        downloadLabel: PropTypes.string,
        autoFocus: PropTypes.bool,
        onBlur: PropTypes.func
    };
    AudioPlayer.defaultProps = {
        audioUrl: '',
        downloadUrl: '',
        onPlay: null,
        onRecord: null,
        onLoadError: null,
        id: '',
        mode: MODES.FULL,
        autoplay: false,
        canPause: true,
        get loadingError() {
            return lang.CANNOT_OPEN_AUDIO;
        },
        get playLabel() {
            return lang.PLAY;
        },
        get pauseLabel() {
            return lang.PAUSE;
        },
        get timeSlider() {
            return lang.TIMELINE_SLIDER;
        },
        get recordLabel() {
            return lang.RECORD;
        },
        get downloadLabel() {
            return lang.DOWNLOAD;
        },
        autoFocus: false,
        onBlur: null
    };
    return AudioPlayer;
}(React.Component));
export { AudioPlayer };
//# sourceMappingURL=AudioPlayer.js.map