import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import classSet from 'classnames';
import Button from 'react-bem-components/lib/Button';
import { i18n } from 'lib/i18n';
import Metrika from 'lib/metrika';

import Form from 'ui/Form';
import Input from 'ui/Input';
import Icon from 'ui/Icon';
import FormMixin from 'lib/FormMixin';

import userValidator from 'validation/user';
import UserActions from 'actions/User';
import UserStore from 'stores/Users';
import AuthStore from 'stores/Auth';

import './index.css';
import './update-aliases.css';

function toEmail(alias) {
    return `${alias}@${AuthStore.getOrganization().getDomain()}`;
}

function toAlias(email) {
    return email.replace(`@${AuthStore.getOrganization().getDomain()}`, '');
}

function toContact(alias) {
    return {
        alias: true,
        main: false,
        synthetic: true,
        type: 'email',
        value: toEmail(alias),
    };
}

const UpdateAliases = React.createClass({

    mixins: [FormMixin],

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

        return {
            newAlias: '',
            aliases: user.get('aliases').toArray(),
            editable: false,
            errors: userValidator.getErrors(),
        };
    },

    componentWillReceiveProps() {
        this.setState(this.getInitialState());
    },

    _notifyStore() {
        const { aliases } = this.state;
        let contacts = UserStore.get(this.props.id).getContacts();

        const filteredAliases = aliases.filter(alias => !_.find(contacts, { alias: true, value: toEmail(alias) }));

        contacts = contacts
            .concat(filteredAliases.map(toContact))
            .filter(contact => !contact.alias || aliases.indexOf(toAlias(contact.value)) !== -1);

        UserActions.updateStore({ aliases, contacts }, this.props.id);
    },

    _addAlias(alias) {
        return this._submit(UserActions.addAlias(alias, this.props.id));
    },

    _removeAlias(alias) {
        return this._submit(UserActions.removeAlias(alias, this.props.id));
    },

    _handleSubmitAlias() {
        const { aliases, newAlias } = this.state;

        Metrika.send(
            'Карточка пользователя',
            'Управление алиасами',
            'Сохранить добавленный алиас'
        );

        this._addAlias(newAlias)
            .then(response => {
                if (!response || !response.errors) {
                    aliases.push(newAlias);
                    this.setState({
                        aliases,
                        editable: false,
                        newAlias: '',
                        errors: null,
                    });
                    this._notifyStore();
                }
            });
    },

    _handleCancelAlias() {
        Metrika.send(
            'Карточка пользователя',
            'Управление алиасами',
            'Отмена добавления алиаса'
        );

        this.setState({
            editable: false,
            newAlias: '',
            errors: null,
        });
    },

    _handleAddAlias() {
        Metrika.send(
            'Карточка пользователя',
            'Управление алиасами',
            'Добавить алиас'
        );

        this.setState({ editable: true });
        setTimeout(() => this.refs.newAlias.focus(), 0);
    },

    _handleNewAliasInput(payload) {
        this.setState({ newAlias: payload.value });
    },

    _removeListItem(index) {
        const { aliases } = this.state;

        if (index < 0 || index > aliases.length - 1) {
            return;
        }

        Metrika.send(
            'Карточка пользователя',
            'Управление алиасами',
            'Удалить алиас'
        );

        this._removeAlias(aliases[index])
            .then(() => {
                aliases.splice(index, 1);
                this.setState({ aliases });
                this._notifyStore();
            });
    },

    _renderList() {
        return this.state.aliases.map((alias, index) => (
            <div className="user-alias" key={index}>
                <div className="user-alias__value" title={alias + toEmail('')}>
                    {alias}<span className="user-alias__domain">{toEmail('')}</span>
                </div>
                <div
                    className="user-alias__remove"
                    onClick={this._removeListItem.bind(this, index)}
                >
                    <Icon type="red-cross" size="s" />
                </div>
            </div>
        ));
    },

    _renderAddButton() {
        return (
            <span className="add-alias" onClick={this._handleAddAlias}>
                <Icon type="plus-circle" size="l" />
                {i18n('user.action.add_alias')}
            </span>
        );
    },

    _renderNewAliasSection() {
        const { editable, newAlias } = this.state;
        let { errors } = this.state;

        if (!editable) {
            return null;
        }

        errors = errors ? errors.toJS() : {};

        return (
            <div className="update-user-alias-form__new-alias">
                <Form.Item unlabelled>
                    <Input
                        ref="newAlias"
                        onChange={this._handleNewAliasInput}
                        val={newAlias}
                        hasClear
                        suffix={toEmail('')}
                        width="available"
                    />
                </Form.Item>

                <Form.Error value={errors._common} mod="standalone" />

                <Form.Buttons mod="left-aligned">
                    <Button
                        text={i18n('common.action.add')}
                        view="action"
                        disabled={!newAlias}
                        onClick={this._handleSubmitAlias}
                    />
                    <Button
                        text={i18n('common.action.cancel')}
                        name="cancel"
                        onClick={this._handleCancelAlias}
                    />
                </Form.Buttons>
            </div>
        );
    },

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

        const className = classSet({
            form: true,
            'update-user-alias-form': true,
            'update-user-alias-form_editable': this.state.editable,
            'update-user-alias-form_empty': !this.state.aliases.length,
        });

        const title = i18n('user.new_alias.title', {
            email: user.get('email'),
        });

        return (
            <Form
                className={className}
                ref="form"
                onSubmit={this._handleFormSubmit}
                autoComplete={false}
            >

                <Form.Title>{title}</Form.Title>

                <div className="update-user-alias-form__alias-list">
                    <Form.Item unlabelled>
                        {this._renderList()}
                    </Form.Item>
                </div>

                <div className="update-user-alias-form__add-alias">
                    <Form.Item unlabelled>
                        {this._renderAddButton()}
                    </Form.Item>
                </div>

                {this._renderNewAliasSection()}
            </Form>
        );
    },

});

UpdateAliases.propTypes = {
    id: PropTypes.string,
    onCancel: PropTypes.func,
};

export default UpdateAliases;
