import React from 'react';
import { Button, Icon } from 'lego-on-react';
import { block } from 'bem-cn';
import { ServiceResourceRequestsStore } from 'lib2/stores';
import notify from 'lib2/notify';
import directory from 'api2/directory';
import toDataObject from 'lib2/toDataObject';

import AvatarUnit from 'components2/AvatarUnit';
import SpinOverlay from 'components2/SpinOverlay';
import Modal from 'components2/Modal';
import WarningIcon from 'components/Icon/Warning';
import QuestionIcon from 'components/Icon/Question';
import CheckListTable from 'components2/CheckListTable';
import Placeholder from 'components2/Placeholder';
import TooltipBox from 'components/TooltipBox';

import { i18n } from 'i18n2';

import './index.css';

const b = block('resource-requests');

const { Thead, Tbody, Tr, Td } = CheckListTable;

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

        this.state = {
            confirmVisible: false,
            text: '',
            busy: false,
        };

        this._onRequestStoreChange = this._onRequestStoreChange.bind(this);
        this._onConfirmCancel = this._onConfirmCancel.bind(this);
        this._onConfirm = this._onConfirm.bind(this);
    }

    componentDidMount() {
        this._requestsStoreListener = ServiceResourceRequestsStore.onChange(this._onRequestStoreChange);

        this._update();
    }

    componentWillUnmount() {
        this._requestsStoreListener.remove();
        this._unmounted = true;
    }

    _onRequestStoreChange() {
        const { serviceSlug, resourceId } = this.props;
        const requests = ServiceResourceRequestsStore.get([serviceSlug, resourceId, 'list']);

        this.setState({
            requests,
        });
    }

    _getText(key, params) {
        const { serviceSlug } = this.props;

        return i18n(`resource_page.${serviceSlug}.${key}`, params) ||
            i18n(`resource_page.default.${key}`, params);
    }

    _update() {
        const { serviceSlug, resourceId, onUpdate } = this.props;

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

        directory
            .send('GET', `/v11/subscription/services/${serviceSlug}/licenses/request/`, {
                query: {
                    per_page: 1000,
                    fields: 'comment,user,user.name,user.position',
                    resource_id: resourceId,
                },
            })
            .then(({ ok, body }) => {
                if (ok && body) {
                    ServiceResourceRequestsStore.set([serviceSlug, resourceId, 'list'], body.result);

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

    _onChangeRequestClick({ object, type }, action) {
        this.setState({
            changeRequest: {
                action,
                object,
                type,
            },
        }, () => {
            if (object.external && action === 'confirm') {
                this.setState({
                    confirmVisible: true,
                });

                return;
            }

            this._applyChanges({ object, type }, action);
        });
    }

    _onConfirmCancel() {
        this.setState({
            confirmVisible: false,
        });
    }

    _onConfirm() {
        this._applyChanges();

        this.setState({
            confirmVisible: false,
        });
    }

    _applyChanges() {
        const { serviceSlug, resourceId, onUpdate } = this.props;
        const { changeRequest: { object, type, action } } = this.state;

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

        directory.send('POST', `/v11/subscription/services/${serviceSlug}/licenses/request/${action}/`, {
            body: JSON.stringify([toDataObject(object, type)]),
            query: { resource_id: resourceId },
        })
            .then(({ ok, body }) => {
                if (body && body.code === 'cancelByUser') {
                    return;
                }

                if (!ok) {
                    return notify(
                        i18n(`backend_errors.${body.code}`) || this._getText('change_relation_error'),
                        'error'
                    );
                }

                notify(
                    this._getText(`${action}_request_success`),
                    'success'
                );

                if (body) {
                    ServiceResourceRequestsStore.set([serviceSlug, resourceId, 'list'], body.result);
                }

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

    render() {
        const { serviceSlug, cls, canChangeRelations, roles } = this.props;
        const { requests, busy, confirmVisible } = this.state;

        if (requests === undefined && busy) {
            return (
                <SpinOverlay
                    progress={busy}
                    size="m"
                    position="center"
                />
            );
        }

        if (!busy && (!requests || requests.length === 0)) {
            return (
                <div className={b({ slug: serviceSlug }).mix(cls)}>
                    <Placeholder
                        cls={b('empty')}
                        icon="no-requests"
                        title={this._getText('empty.requests_title')}
                        description={this._getText('empty.requests_description')}
                    />
                </div>
            );
        }

        return (
            <div className={b({ slug: serviceSlug }).mix(cls)}>
                <CheckListTable cls={b('table')}>
                    <Thead>
                        <Tr>
                            <Td role="request">
                                <span className={b('table-header-request')}>
                                    {this._getText('fields.user')}
                                </span>
                            </Td>
                            <Td role="type">
                                <span className={b('table-header-type')}>
                                    {this._getText('fields.accessory')}
                                </span>
                            </Td>
                            <Td role="role">
                                <span className={b('table-header-role')}>
                                    {this._getText('fields.role')}
                                </span>
                            </Td>
                            <Td role="actions" />
                        </Tr>
                    </Thead>
                    <Tbody>
                        {requests.map(({ object, object_type: type, name, comment }) => (
                            <Tr key={`${type}-${object.id}`}>
                                <Td role="request">
                                    <AvatarUnit
                                        object={object}
                                        type={type}
                                    />
                                </Td>
                                <Td role="type">
                                    <div className={b('role')}>{roles && roles[name] || name}</div>
                                    {comment && <div className={b('comment')}>{comment}</div>}
                                </Td>
                                <Td role="role">
                                    {this._getText(`user_accessory.${object.external ? 'external' : 'worker'}`)}
                                    {object.external && (
                                        <TooltipBox
                                            key="toolBox"
                                            tip={this._getText('user_is_external')}
                                            interaction="hover"
                                            theme="normal"
                                            size="s"
                                        >
                                            <Icon
                                                cls={b('tip-icon')}
                                                glyph="yes"
                                            >
                                                <QuestionIcon />
                                            </Icon>
                                        </TooltipBox>
                                    )}
                                </Td>
                                <Td role="actions">
                                    {canChangeRelations &&
                                    <Button
                                        cls={b('button', { type: 'deny' })}
                                        theme="normal"
                                        size="m"
                                        text={i18n('resource_page.action_text.deny')}
                                        onClick={() => this._onChangeRequestClick({ object, type }, 'deny')}
                                    />}
                                    {canChangeRelations &&
                                    <Button
                                        cls={b('button', { type: 'confirm' })}
                                        theme="action"
                                        size="m"
                                        text={i18n('resource_page.action_text.confirm')}
                                        onClick={() => this._onChangeRequestClick({ object, type }, 'confirm')}
                                    />}
                                </Td>
                            </Tr>
                        ))}
                    </Tbody>
                </CheckListTable>
                <Confirm
                    visible={confirmVisible}
                    onCancel={this._onConfirmCancel}
                    onConfirm={this._onConfirm}
                    text={{
                        title: this._getText('confirm_request_warning_title'),
                        warning: this._getText('confirm_request_warning_header'),
                        message: this._getText('confirm_request_warning_message'),
                    }}
                />
                <SpinOverlay
                    progress={busy}
                    size="m"
                    position="center"
                    spinDelay={500}
                />
            </div>
        );
    }
}

const Confirm = ({ text: { title, warning, message }, visible, onCancel, busy, onConfirm }) => (
    <Modal
        cls={b('confirm')}
        visible={visible}
    >
        <Modal.Title>
            {title}
        </Modal.Title>
        <Modal.CloseButton onClick={onCancel} />
        <Modal.Body>
            <div className={b('warning')}>
                <Icon glyph="yes" cls={b('warning-icon')}>
                    <WarningIcon />
                </Icon>
                {warning}
            </div>
            {message}
        </Modal.Body>
        <Modal.ConfirmActions
            onConfirm={onConfirm}
            onCancel={onCancel}
            confirmCaption={i18n('common.action.confirm')}
        />
        <Modal.Busy visible={busy} />
    </Modal>
);
