import React from 'react';
import { Icon, Button } from 'lego-on-react';
import { block } from 'bem-cn';
import InfoIcon from 'components/Icon/Info';
import TrashIcon from 'components/Icon/Trash';
import Modal from 'components2/Modal';
import SearchInput from 'components2/SearchInput';
import AvatarUnit from 'components2/AvatarUnit';
import CalculatedServicePricing from 'components2/CalculatedServicePricing';
import TooltipBox from 'components/TooltipBox';
import toObjectKey from 'lib2/toObjectKey';
import toDataObject from 'lib2/toDataObject';
import notify from 'lib2/notify';
import directory from 'api2/directory';
import metrika from 'api2/metrika';
import { ServiceSubscribersStore, PricingStore } from 'lib2/stores';
import { i18n, pluralize } from 'i18n2';

import './index.css';

const b = block('subscription-modal');

const RootDepartment = {
    object: { id: 1, name: i18n('common.dept.all_employees') },
    type: 'department',
};

const ContainerTypes = ['department', 'group'];

export default class SubscriptionModal extends React.PureComponent {
    constructor(props) {
        super(props);

        this.state = {
            busy: true,
            cancelCount: 0,
            selectedSubscribers: new Map(),
        };

        this._update = this._update.bind(this);
        this._isSearchItemChecked = this._isSearchItemChecked.bind(this);
        this._onSelect = this._onSelect.bind(this);
        this._applyChanges = this._applyChanges.bind(this);
        this._addAll = this._addAll.bind(this);
    }

    componentDidMount() {
        this._update();

        this._storeListeners = [
            ServiceSubscribersStore.onChange(this._update),
            PricingStore.onChange(this._update),
        ];
    }

    componentWillUnmount() {
        this._storeListeners.forEach(listener => listener.remove());
        this._unmounted = true;
    }

    componentDidUpdate(prevProps) {
        if (this.props.serviceSlug !== prevProps.serviceSlug) {
            this._update();
        }
    }

    _update() {
        let existingSubscribers = ServiceSubscribersStore.get([this.props.serviceSlug, 'list']);
        let currency = PricingStore.get('currency');

        this.setState({
            existingSubscribers,
            currency,
            busy: existingSubscribers === undefined || currency === undefined,
        });
    }

    _isSearchItemChecked(item) {
        let {
            existingSubscribers = [],
            selectedSubscribers = new Map(),
        } = this.state;

        return [
            ...selectedSubscribers.keys(),
            ...existingSubscribers.map(toObjectKey),
        ].includes(toObjectKey(item));
    }

    _onSelect(item) {
        let { selectedSubscribers } = this.state;
        let { object, type } = item;

        selectedSubscribers.set(toObjectKey(object, type), item);

        this.setState({
            selectedSubscribers: new Map(selectedSubscribers),
        });
    }

    _remove(object, type) {
        let { selectedSubscribers } = this.state;

        selectedSubscribers.delete(toObjectKey(object, type));

        this.setState({
            selectedSubscribers: new Map(selectedSubscribers),
        });
    }

    _addAll() {
        let { selectedSubscribers } = this.state;

        selectedSubscribers.set(toObjectKey(RootDepartment), RootDepartment);

        this.setState({
            selectedSubscribers: new Map(selectedSubscribers),
        });
    }

    _applyChanges() {
        let { serviceSlug, onConfirm } = this.props;

        let {
            existingSubscribers = [],
            selectedSubscribers = new Map(),
        } = this.state;

        this.setState({
            busy: true,
        });

        directory
            .send('PUT', `/v11/subscription/services/${serviceSlug}/licenses/`, {
                body: JSON.stringify([
                    ...selectedSubscribers.values(),
                    ...existingSubscribers,
                ].map(toDataObject)),
            })
            .then(({ ok, body }) => {
                if (!ok) {
                    let message = i18n(`backend_errors.${body.code}`) ||
                        pluralize(selectedSubscribers.size, i18n('licenses.add.error2'), '${objects}');

                    return notify(message, 'error');
                }

                notify(
                    pluralize(selectedSubscribers.size, i18n('licenses.add.success2'), '${objects}'),
                    'success'
                );

                metrika.reachGoal('AddPaidUsers');
                ServiceSubscribersStore.set([serviceSlug, 'list'], body);

                this._unmounted || this._clearList();

                if (onConfirm) {
                    onConfirm();
                }
            })
            .finally(() => {
                if (!this._unmounted) {
                    this.setState({
                        busy: false,
                    });
                }
            });
    }

    _clearList() {
        this.setState({ selectedSubscribers: new Map() });
    }

    onCancel = () => {
        const { cancelCount } = this.state;
        const { onCancel } = this.props;

        onCancel && onCancel();

        this._clearList();
        this.setState({ cancelCount: cancelCount + 1 });
    }

    render() {
        let {
            serviceSlug,
            visible,
            subscriberSearchType,
        } = this.props;

        let { busy, existingSubscribers, selectedSubscribers, cancelCount } = this.state;

        return (
            <Modal
                cls={b()}
                visible={visible}
            >
                <Modal.Title>
                    {i18n('licenses.add_subscribers.title.search')}
                </Modal.Title>
                <Modal.CloseButton onClick={this.onCancel} />
                <Modal.Body>
                    <SearchInput
                        onSelect={this._onSelect}
                        searchType={subscriberSearchType}
                        checked={this._isSearchItemChecked}
                        key={cancelCount}
                    />
                    {selectedSubscribers.size === 0 ?
                        <div
                            className={b('list-placeholder')}
                            dangerouslySetInnerHTML={{
                                __html: i18n(`licenses.new_subscriptions.placeholder.${serviceSlug}`, {
                                    add_user_url: '/portal/admin#add-user',
                                    add_user_target: '_blank',
                                }),
                            }}
                        /> :
                        <div className={b('list')}>
                            {[...selectedSubscribers.values()].map(({ object, type }) => (
                                <div
                                    className={b('list-item')}
                                    key={toObjectKey(object, type)}
                                >
                                    <AvatarUnit
                                        object={object}
                                        type={type}
                                    />
                                    {ContainerTypes.includes(type) &&
                                    <div className={b('control', { role: 'info' })}>
                                        <TooltipBox
                                            tip={i18n('licenses.container_tooltip')}
                                            to="bottom"
                                            size="s"
                                            theme="normal"
                                        >
                                            <Icon glyph="yes"><InfoIcon /></Icon>
                                        </TooltipBox>
                                    </div>}
                                    <div
                                        className={b('control', { role: 'remove-item' })}
                                        onClick={() => this._remove(object, type)}
                                    >
                                        <Icon glyph="yes"><TrashIcon /></Icon>
                                    </div>
                                </div>
                            ))}
                        </div>}
                    <div className={b('actions')}>
                        {selectedSubscribers.size === 0 &&
                        <Button
                            cls={b('button', { role: 'add-all' })}
                            text={i18n('licenses.new_subscriptions.add_all')}
                            theme="normal"
                            size="m"
                            onClick={this._addAll}
                            disabled={subscriberSearchType === 'user'}
                        />}
                        {selectedSubscribers.size !== 0 &&
                        <Button
                            cls={b('button', { role: 'apply' })}
                            text={i18n('licenses.save_subscriptions')}
                            theme="action"
                            size="m"
                            disabled={selectedSubscribers.size === 0}
                            onClick={this._applyChanges}
                        />}
                    </div>
                    <CalculatedServicePricing
                        serviceSlug={serviceSlug}
                        existingSubscribers={existingSubscribers}
                        selectedSubscribers={selectedSubscribers}
                    />
                </Modal.Body>
                <Modal.Busy visible={busy} />
            </Modal>
        );
    }
}
