import './index.css';

import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import { Button, TextInput, Dropdown, Menu, Popup } from 'lego-on-react';

import { block } from 'bem-cn';
import TooltipBox from 'components/TooltipBox';

import OrganizationStore from 'stores/Organizations';
import OrganizationActions from 'actions/OrgSetup';
import { i18n } from 'lib/i18n';
import Metrika from 'lib/metrika';
import Url from 'lib/Url';
import BindWidgetSuccess from './components/BindWidgetSuccess';

const newOrgItem = {
    id: '*',
    name: i18n('bind.widget.label.new'),
};

const b = block('bind-widget');

const BindWidget = React.createClass({

    getInitialState() {
        const firstAvailableOrg = this.props.organizations.find(({ binding_available: available }) => available);

        return {
            text: '',
            loading: false,
            error: null,
            success: null,
            orgId: firstAvailableOrg ? firstAvailableOrg.org_id : '',
        };
    },

    _initInput(input) {
        if (input) {
            input.focus();
        }
    },

    _onChange(text) {
        this.setState({ text });
    },

    _getData() {
        const { text, orgId } = this.state;
        const { relations, resourceId, serviceSlug } = this.props;

        const data = {
            service: {
                slug: serviceSlug,
                resource: {
                    id: resourceId,
                    relations,
                },
            },
        };

        if (orgId !== newOrgItem.id) {
            data.org_id = Number(orgId);
        } else if (text) {
            data.organization = {
                name: text,
                source: Url.getSourceParams(`bind_${serviceSlug}`),
            };
        }

        return data;
    },

    _onSubmit(e) {
        e.preventDefault();

        this.setState({
            loading: true,
            error: null,
        });

        const data = this._getData();

        OrganizationActions.bindWithResource(data, { 'dry-run': 0 })
            .finally(() => {
                this.setState({ loading: false });
            })
            .then(response => {
                if (response.errors) {
                    this._setError();

                    return;
                }

                this._onOrganizationBind(response);
            })
            .catch(err => {
                this._setError();

                throw err;
            });
    },

    _onOrganizationBind({ orgId }) {
        const { orgId: currentOrgId, serviceSlug } = this.props;

        Metrika.reachGoal(`${_.capitalize(serviceSlug)}BoundTo${currentOrgId ? 'Existing' : 'New'}Organization`);

        this.props.onSend({ org_id: orgId });

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

    _setError() {
        this.setState({ error: this._getText('bind.widget.error') });
    },

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

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

    _renderInputContent() {
        const { text } = this.state;

        return (
            <div className={b('org-name')} key="ord-name">
                <label className={b('input-label')} htmlFor="widget-input">
                    {i18n('bind.widget.input.label')}
                </label>
                <TextInput
                    id="widget-input"
                    ref={this._initInput}
                    theme="normal"
                    size="m"
                    pin="round-round"
                    cls={b('input')}
                    text={text}
                    focused
                    autocomplete={false}
                    onChange={this._onChange}
                    placeholder={i18n('bind.widget.input.placeholder')}
                />
            </div>
        );
    },

    _onMenuItemClick(e, orgId) {
        if (this._menu) {
            this._menu._onOutsideClick(); // закроет меню
        }

        this.setState({
            orgId,
            error: null,
        });
    },

    _init(menu) {
        if (menu) {
            this._menu = menu;
        }
    },

    _renderContentWithOrgs() {
        const { orgId } = this.state;
        const { organizations } = this.props;

        const respOrgText = this._getText('bind.widget.text3.org');

        const enabledItems = [];
        const enabledNewOrgItems = [];
        const disabledItems = [];

        organizations.forEach(({ org_id: id, binding_available: enabled, reason }) => {
            if (enabled) {
                if (id !== newOrgItem.id) {
                    enabledItems.push(
                        <Menu.Item
                            cls={b('select-item')}
                            val={id}
                            key={id}
                            onClick={this._onMenuItemClick}
                        >
                            {OrganizationStore.getOrgName(id.toString())}
                        </Menu.Item>
                    );
                } else {
                    enabledNewOrgItems.push(
                        <Menu.Item
                            cls={b('select-item')}
                            val={id}
                            key={id}
                            onClick={this._onMenuItemClick}
                        >
                            {newOrgItem.name}
                        </Menu.Item>
                    );
                }
            } else {
                disabledItems.push(
                    <Menu.Item
                        cls={b('select-item')}
                        val={id}
                        key={id}
                        disabled
                        onClick={this._onMenuItemClick}
                    >
                        <TooltipBox
                            tip={this._getText(`bind.widget.error.${reason}`)}
                            to="right"
                            size="s"
                            theme="normal"
                        >
                            {OrganizationStore.getOrgName(id.toString())}
                        </TooltipBox>
                    </Menu.Item>
                );
            }
        });

        // Если только одна организация и она новая, но не показываем селект
        const availableOrgs = organizations.filter(({ binding_available: available }) => available);
        const showSelect = availableOrgs.length > 1 ||
            availableOrgs.length === 1 && availableOrgs[0].org_id !== newOrgItem.id;

        return (
            <div
                className={b('content')}
                key="content"
            >
                <h2 className={b('title')} key="title">
                    {this._getText('bind.widget.title')}
                </h2>
                {showSelect && (
                    <label className={b('input-label')}>
                        {i18n('bind.widget.name.label')}
                    </label>
                )}
                {showSelect && (
                    <Dropdown
                        size="m"
                        switcher="button2"
                        theme="normal"
                        popup={(
                            <Popup
                                cls={b('popup')}
                                theme="normal"
                                directions={[
                                    'bottom-left',
                                ]}
                            >
                                <Menu
                                    cls={b('options')}
                                    theme="normal"
                                    width="max"
                                    type="radio"
                                    size="m"
                                    val={orgId}
                                >
                                    {enabledItems.length > 0 && (
                                        <Menu.Group>
                                            {enabledItems}
                                        </Menu.Group>
                                    )}
                                    {enabledNewOrgItems.length > 0 && (
                                        <Menu.Group>
                                            {enabledNewOrgItems}
                                        </Menu.Group>
                                    )}
                                    {disabledItems.length > 0 && (
                                        <Menu.Group>
                                            {disabledItems}
                                        </Menu.Group>
                                    )}
                                </Menu>
                            </Popup>
                        )}
                        cls={b('dropdown')}
                        hasTick
                        ref={this._init}
                    >
                        <Dropdown.Switcher>
                            {orgId === newOrgItem.id ? newOrgItem.name : OrganizationStore.getOrgName(orgId.toString())}
                        </Dropdown.Switcher>
                    </Dropdown>
                )}
                <div
                    key="text"
                    className={b('text')}
                >
                    {orgId === newOrgItem.id ?
                        `${this._getText('bind.widget.text1')} ${this._getText('bind.widget.text2')}` :
                        respOrgText}
                </div>
                {orgId === newOrgItem.id && this._renderInputContent()}
            </div>
        );
    },

    render() {
        const { onCancel, serviceSlug } = this.props;
        const { orgId, error, loading, success } = this.state;

        if (success) {
            return (
                <BindWidgetSuccess
                    serviceSlug={serviceSlug}
                    onCancel={onCancel}
                    orgName={OrganizationStore.getOrgName(orgId.toString())}
                />
            );
        }

        let content = [this._renderContentWithOrgs()];

        if (error) {
            content.push(
                <div
                    key="error"
                    className="bind-widget__error"
                >
                    {error}
                </div>
            );
        }

        return (
            <div className={b({ loading: loading ? 'yes' : 'no' })}>
                {content}
                <Button
                    theme="action"
                    view="default"
                    tone="default"
                    size="m"
                    cls={b('button', { role: 'submit' })}
                    progress={loading}
                    onClick={this._onSubmit}
                >
                    {orgId === newOrgItem.id ?
                        this._getText('bind.widget.button.submit') :
                        this._getText('bind.widget.button.submit.org')}
                </Button>
                <Button
                    theme="normal"
                    size="m"
                    cls={b('button', { role: 'cancel' })}
                    onClick={onCancel}
                >
                    {i18n('bind.widget.button.cancel')}
                </Button>
            </div>
        );
    },
});

BindWidget.propTypes = {
    relations: PropTypes.array.isRequired,
    resourceId: PropTypes.string.isRequired,
    serviceSlug: PropTypes.string.isRequired,
    orgId: PropTypes.string,
    orgName: PropTypes.string,
    onCancel: PropTypes.func.isRequired,
    onSend: PropTypes.func.isRequired,
};

export default BindWidget;
