import PropTypes from 'prop-types';
import React from 'react';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import Menu from 'react-bem-components/lib/Menu';
import { Permissions } from 'constants/Common';
import StoreMixin from 'lib/StoreMixin';
import ModalActions from 'actions/Modal';
import UserModalActions from 'actions/Modal.User';
import UIActions from 'actions/UI';
import UserActions from 'actions/User';
import submit from 'services/submit';
import { i18n } from 'lib/i18n';
import Url from 'lib/Url';
import Metrika from 'lib/metrika';

import PermissionStore from 'stores/Permissions';
import AuthStore from 'stores/Auth';
import UserStore from 'stores/Users';

import UpdateSection from 'components/User/UpdateSection';
import UpdateForm from 'components/User/Forms/Update';
import UpdateContactsForm from 'components/User/Forms/UpdateContacts';
import UpdateAliasesForm from 'components/User/Forms/UpdateAliases';
import ChangePasswordForm from 'components/User/Forms/ChangePassword';

const INPLACE_EDITING_ENABLED = true;

const MENU_OPTIONS = [{
    text: i18n('user.edit_menu.edit_info'),
    metrika: 'Редактировать информацию',
    val: 'edit_info',
    available(user) {
        return PermissionStore.contains(Permissions.EDIT_USER_INFO, user, true);
    },
}, {
    text: i18n('user.edit_menu.manage_aliases'),
    metrika: 'Управление алиасами',
    val: 'manage_aliases',
    available(user) {
        return PermissionStore.contains(Permissions.CHANGE_ALIAS, user, true);
    },
}, {
    text: i18n('user.edit_menu.change_password'),
    metrika: 'Изменить пароль',
    val: 'change_password',
    available(user) {
        return PermissionStore.contains(Permissions.CHANGE_USER_PASSWORD, user);
    },
}, {
    text: i18n('user.edit_menu.block_user'),
    metrika: 'Заблокировать пользователя',
    val: 'block',
    available(user) {
        return PermissionStore.contains(Permissions.BLOCK_USER, user) &&
            user.get('is_enabled');
    },
}, {
    text: i18n('user.edit_menu.unblock_user'),
    metrika: 'Разблокировать пользователя',
    val: 'unblock',
    available(user) {
        return PermissionStore.contains(Permissions.BLOCK_USER, user) &&
            !user.get('is_enabled');
    },
}, {
    text: i18n('user.edit_menu.grant_admin_access'),
    metrika: 'Сделать администратором',
    val: 'grant_access',
    available(user) {
        return PermissionStore.contains(Permissions.MAKE_ADMIN, user) &&
            !user.isAdmin();
    },
}, {
    text: i18n('user.edit_menu.revoke_admin_access'),
    metrika: 'Отозвать права администратора',
    val: 'revoke_access',
    available(user) {
        return PermissionStore.contains(Permissions.MAKE_ADMIN, user) &&
            user.isAdmin();
    },
}, {
    text: i18n('user.edit_menu.dismiss_user'),
    metrika: 'Удалить',
    val: 'dismiss',
    available(user) {
        return PermissionStore.contains(Permissions.DISMISS_USER, user) &&
            !user.get('is_dismissed');
    },
}];

const METRIKA_MAP = {};

MENU_OPTIONS.forEach(item => METRIKA_MAP[item.val] = item.metrika);

const EditMenu = React.createClass({

    mixins: [StoreMixin, PureRenderMixin],

    getStoreState() {
        const { id } = this.props;
        const user = UserStore.get(id);

        return {
            user,
            key: this.hashCode(),
            menuOptions: this._getMenuOptions(user),
        };
    },

    _getMenuOptions(user) {
        if (!user) {
            return [];
        }

        return MENU_OPTIONS.filter(item => item.available === undefined || item.available(user));
    },

    componentDidMount() {
        this.subscribe([UserStore, PermissionStore]);
    },

    componentWillReceiveProps(nextProps) {
        if (nextProps.id) {
            // изменение ключа позволяет обойти ограничение
            // на перерисовку бэм-компонента меню
            this.setState({ key: nextProps.id });
        }
    },

    _handleFormDone() {
        ModalActions.close();
    },

    _handleMenuSelect(payload) {
        const { user } = this.state;
        const { id, onSelect } = this.props;

        Metrika.send(
            'Карточка пользователя', 'КМ',
            METRIKA_MAP[payload.value], Metrika.getUserType()
        );

        const formProps = {
            id,
            onSubmit: this._handleFormDone,
            onCancel: this._handleFormDone,
        };

        switch (payload.value) {
            case 'edit_info':
                if (INPLACE_EDITING_ENABLED) {
                    UIActions.editUser({
                        component: UpdateSection,
                        props: { id },
                    });
                } else if (PermissionStore.contains(Permissions.EDIT_USER, user)) {
                    ModalActions.open({
                        component: UpdateForm,
                        props: formProps,
                    });
                } else if (PermissionStore.contains(Permissions.EDIT_USER_CONTACTS, user)) {
                    ModalActions.open({
                        component: UpdateContactsForm,
                        props: formProps,
                    });
                }
                break;

            case 'manage_aliases':
                if (PermissionStore.contains(Permissions.EDIT_USER, user)) {
                    ModalActions.open({
                        component: UpdateAliasesForm,
                        props: {
                            id,
                            onCancel: this._handleFormDone,
                        },
                    });
                }
                break;

            case 'change_password':
                if (PermissionStore.contains(Permissions.CHANGE_USER_PASSWORD, user)) {
                    ModalActions.open({
                        component: ChangePasswordForm,
                        props: formProps,
                    });
                } else {
                    Url.open(AuthStore.getPasswordChangeUrl());
                }
                break;

            case 'block':
                submit(UserActions.blockUser(id), {
                    failure: i18n('user.status.failed_to_block_user'),
                });
                break;

            case 'unblock':
                submit(UserActions.unblockUser(id), {
                    success: i18n('user.status.user_unblocked'),
                    failure: i18n('user.status.failed_to_unblock_user'),
                });
                break;

            case 'grant_access':
                submit(UserActions.grantAdminAccess(id), {
                    success: i18n('common.status.done'),
                    failure: i18n('common.status.failed'),
                });
                break;

            case 'revoke_access':
                submit(UserActions.revokeAdminAccess(id), {
                    success: i18n('common.status.done'),
                    failure: i18n('common.status.failed'),
                });
                break;

            case 'grant_deputy_admin_access':
                submit(UserActions.grantDeputyAdminAccess(id), {
                    success: i18n('common.status.done'),
                    failure: i18n('common.status.failed'),
                });
                break;

            case 'revoke_deputy_admin_access':
                submit(UserActions.revokeDeputyAdminAccess(id), {
                    success: i18n('common.status.done'),
                    failure: i18n('common.status.failed'),
                });
                break;

            case 'dismiss':
                UserModalActions.dismiss(id);
                break;

            /* no default */
        }

        if (onSelect) {
            onSelect(payload);
        }
    },

    render() {
        const { key, menuOptions } = this.state;

        if (menuOptions.length === 0) {
            return null;
        }

        return (
            <Menu
                key={key}
                options={menuOptions}
                onSelect={this._handleMenuSelect}
            />
        );
    },
});

EditMenu.propTypes = {
    id: PropTypes.string,
    onSelect: PropTypes.func,
};

export default EditMenu;
