'use strict';

import React from 'react';
import {Icon} from '../Icon';
import {Button} from '../Button';

import {getProcessedPercentage, KEY_CODE} from './utils';
import PropTypes from 'prop-types';

import lang from '../../../lang/common/index-en_US';

const VOLUME_BAR = 'audio-volume-bar';
const VOLUME_INDICATOR = 'audio-volume-current-pos';
const STEP = 0.03;

export class VolumeControl extends React.Component<any, any> {
    static propTypes = {
        setVolume: PropTypes.func.isRequired,
        volume: PropTypes.number.isRequired,
        isMuted: PropTypes.bool,
        id: PropTypes.string,
        muteLabel: PropTypes.string,
        unmuteLabel: PropTypes.string,
        volumeSlider: PropTypes.string
    };

    static defaultProps = {
        isMuted: false,
        id: 'volumeControl',
        get muteLabel() {
            return lang.MUTE;
        },
        get unmuteLabel() {
            return lang.UNMUTE;
        },
        get volumeSlider() {
            return lang.VOLUME_SLIDER;
        }
    };

    initialized: any;
    volumeRightBoundary: any;
    draggingVolume: any;

    componentDidMount() {
        if (!this.initialized) {
            let volumeBar = this.refs[VOLUME_BAR] as any;
            let volumeIndicator = this.refs[VOLUME_INDICATOR] as any;
            this.volumeRightBoundary = 1 - volumeIndicator.offsetWidth / volumeBar.offsetWidth;
            // Drag start
            volumeBar.addEventListener('mousedown', this.volumeDragStart);
            // Drag end
            window.addEventListener('mouseup', this.windowDragEnd);
            //Key down
            volumeIndicator.addEventListener('keydown', this.progressKeyDown);
        }
        this.initialized = true;
    }

    componentWillUnmount() {
        if (this.initialized) {
            (this.refs[VOLUME_INDICATOR] as any).removeEventListener(
                'keydown',
                this.progressKeyDown
            );
            window.removeEventListener('mouseup', this.windowDragEnd);
            window.removeEventListener('mousedown', this.volumeDragStart);
            window.removeEventListener('mousemove', this.volumeDrag);
        }
    }

    volumeDrag = e => {
        let volumeBar = this.refs[VOLUME_BAR] as any;
        let volumeIndicator = this.refs[VOLUME_INDICATOR] as any;
        let distance = e.clientX - volumeBar.getBoundingClientRect().left;
        let processPercentage = getProcessedPercentage(
            distance,
            volumeBar.offsetWidth,
            volumeIndicator.offsetWidth / 2
        );
        this.props.setVolume(processPercentage);
    };

    volumeDragStart = e => {
        e.stopPropagation();
        e.preventDefault();
        this.draggingVolume = true;
        this.volumeDrag(e);
        window.addEventListener('mousemove', this.volumeDrag);
    };

    windowDragEnd = () => {
        if (this.draggingVolume) {
            window.removeEventListener('mousemove', this.volumeDrag);
            this.draggingVolume = false;
        }
    };

    volumeKeyHandler(step = STEP) {
        let {volume, isMuted} = this.props;
        let currentVolume = isMuted ? step : volume + step;
        if (currentVolume < 0) {
            currentVolume = 0;
        } else if (currentVolume > 1) {
            currentVolume = 1;
        }
        this.props.setVolume(currentVolume);
    }

    progressKeyDown = e => {
        let isValidKey = false;

        switch (e.keyCode) {
            case KEY_CODE.RIGHT:
            case KEY_CODE.UP:
                isValidKey = true;
                this.volumeKeyHandler(STEP);
                break;
            case KEY_CODE.LEFT:
            case KEY_CODE.DOWN:
                isValidKey = true;
                this.volumeKeyHandler(-STEP);
                break;
            case KEY_CODE.PAGEUP:
                isValidKey = true;
                this.volumeKeyHandler(STEP * 3);
                break;
            case KEY_CODE.PAGEDOWN:
                isValidKey = true;
                this.volumeKeyHandler(-STEP * 3);
                break;
            case KEY_CODE.END:
                isValidKey = true;
                this.volumeKeyHandler(1);
                break;
            case KEY_CODE.HOME:
                isValidKey = true;
                this.volumeKeyHandler(-1);
                break;
        }

        if (isValidKey) {
            e.stopPropagation();
            e.preventDefault();
        }
    };

    render() {
        let {volume, isMuted, id, setVolume} = this.props;
        let volumePercent = volume * 100;
        let percent = volumePercent + '%';
        let indicatorStyle: any = {};

        if (isMuted) {
            volumePercent = 0;
            percent = '0%';
            indicatorStyle.left = 0;
        } else if (volume < 1) {
            indicatorStyle.left = percent;
            if (this.volumeRightBoundary && volume > this.volumeRightBoundary) {
                indicatorStyle.left = '100%';
                volumePercent = 100;
                indicatorStyle.WebkitTransform = 'translateX(-100%)';
                indicatorStyle.transform = indicatorStyle.WebkitTransform;
            }
        }

        return (
            <div className="audio-volume" data-test-automation-id={`audioVolume${id}`}>
                <Button
                    iconOnly
                    bsStyle="link"
                    testAutomationId={`audioVolumeMute${id}`}
                    className="audio-volume-button"
                    aria-pressed={isMuted}
                    aria-label={isMuted ? this.props.unmuteLabel : this.props.muteLabel}
                    onClick={() => {
                        setVolume(volume, !isMuted);
                    }}>
                    <Icon name={isMuted ? 'mute' : 'volume'} />
                </Button>
                <div
                    ref={VOLUME_BAR}
                    className={`audio-process-bar ${VOLUME_BAR}`}
                    data-test-automation-id={`audioVolumeBar${id}`}>
                    <div
                        className="audio-process-bar-total"
                        data-test-automation-id={`audioVolumeTotal${id}`}
                    />
                    <div
                        className="audio-process-bar-left"
                        style={{width: percent}}
                        data-test-automation-id={`audioVolumeLeft${id}`}
                    />
                    <div
                        role="slider"
                        tabIndex={0}
                        aria-label={this.props.volumeSlider}
                        aria-valuemin={0}
                        aria-valuemax={100}
                        aria-valuenow={Math.round(volumePercent)}
                        aria-valuetext={Math.round(volumePercent) + '%'}
                        ref={VOLUME_INDICATOR}
                        className="audio-process-indicator"
                        style={indicatorStyle}
                        data-test-automation-id={`audioVolumeIndicator${id}`}
                    />
                </div>
            </div>
        );
    }
}
