import React from 'react';
import { block } from 'bem-cn';
import { Icon } from 'lego-on-react';
import RequestMetadata from 'components2/RequestMetadata';
import { NotificationStore } from 'lib2/stores';
import { i18n } from 'i18n2';

import './index.css';
import './animation.css';

const bQueue = block('status-notification-queue');
const bItem = block('status-notification');

class NotificationQueue extends React.PureComponent {
    constructor() {
        super();
        this.state = {};

        this._update = this._update.bind(this);
    }

    componentDidMount() {
        this._update();
        this._storeListener = NotificationStore.onChange(this._update);
    }

    componentWillUnmount() {
        this._storeListener.remove();
    }

    _update() {
        this.setState({
            queue: NotificationStore.get('queue'),
        });
    }

    _remove(id) {
        let { queue } = this.state;

        if (!queue || !queue.length) {
            return;
        }

        let closedItem = queue.find(item => item.id === id);

        if (closedItem) {
            closedItem.remove();
        }
    }

    render() {
        let { queue } = this.state;

        if (!queue || !queue.length) {
            return null;
        }

        return (
            <div className={bQueue()}>
                {queue.map(({ id, onClose, onCancel, ...otherProps }) => {
                    let _onCancel;

                    // _onCancel определён, только если явно передан обработчик отмены
                    if (onCancel) {
                        _onCancel = () => {
                            this._remove(id);
                            onCancel(id);
                        };
                    }

                    // _onClose определён всегда
                    let _onClose = () => {
                        this._remove(id);
                        onClose && onClose(id);
                    };

                    return (
                        <Notification
                            onClose={_onClose}
                            onCancel={_onCancel}
                            {...otherProps}
                            key={id}
                        />
                    );
                })}
            </div>
        );
    }
}

const ANIMATION_GAP = 2000;

const Notification = ({ type, message, ttl, onClose, onCancel }) => {
    if (!message) {
        return null;
    }

    let animationStyle;

    if (typeof ttl === 'number') {
        // CSS-анимация скрытия начнётся на ANIMATION_GAP раньше,
        // чем нотификация удалится из очереди и из DOM
        let hideDelay = Math.max(ttl - ANIMATION_GAP, 0) / 1e3;

        animationStyle = { animationDelay: `0s, ${hideDelay}s` };
    } else {
        animationStyle = { animation: 'none' };
    }

    return (
        <div
            className={bItem({ type })}
            style={animationStyle}
        >
            <div
                className={bItem('content')}
                role="status"
            >
                {message}
            </div>
            {type === 'error' && <RequestMetadata cls={bItem('meta')} />}
            {onCancel && (
                <div className={bItem('actions')}>
                    <span
                        className={bItem('action', { role: 'cancel' })}
                        onClick={onCancel}
                    >
                        {i18n('common.action.cancel')}
                    </span>
                </div>
            )}
            <div
                className={bItem('close-button')}
                onClick={onClose}
                aria-label={i18n('common.action.close')}
            >
                <Icon glyph="type-cross" />
            </div>
        </div>
    );
};

export default NotificationQueue;
