import React from 'react';
import ReactDOM from 'react-dom';
import _ from 'lodash';
import BindWidget from 'components/BindWidget';
import OrganizationActions from 'actions/OrgSetup';
import Url from 'lib/Url';

import './index.css';

const BindWidgetLayout = React.createClass({

    getInitialState() {
        return {
            enabled: false,
            origin: null,
            roles: [],
            orgName: '',
            resourceId: null,
            serviceSlug: '',
        };
    },

    // unsafe constructor
    componentWillMount() {
        this._sizeUpdateInterval = null;
        this._height = 0;
        this._width = 0;
        this._widget = null;
    },

    componentDidMount() {
        const name = window.name;

        this._startListenPong();

        this._postMessage('connect_resource_request', { name }, '*');
    },

    componentWillUnmount() {
        clearInterval(this._sizeUpdateInterval);
        this._stopListenPong();
    },

    _onChangeSize() {
        const container = ReactDOM.findDOMNode(this._getWidgetRef());
        let height = this._height;
        let width = this._width;

        if (container) {
            height = container.offsetHeight;
            width = container.offsetWidth;
        }

        if (this._height !== height || this._width !== width) {
            this._height = height;
            this._width = width;
            this._postSize();
        }
    },

    _startListenPong() {
        this._stopListenPong();
        window.addEventListener('message', this._onWindowMessage, false);
    },

    _stopListenPong() {
        window.removeEventListener('message', this._onWindowMessage, false);
    },

    _createMessageData(type, data, name) {
        return _.assign({ message: type, name }, data);
    },

    _postSize() {
        this._postMessage('connect_bind_widget_size', {
            size: {
                height: this._height,
                width: this._width,
            },
        });
    },

    _postMessage(type, data, origin = this.state.origin) {
        const name = window.name;
        const messageData = this._createMessageData(type, data, name);

        window.parent.postMessage(messageData, origin);
    },

    _onCancel() {
        this._postMessage('connect_bind_widget_closed');
    },

    _onSend(data) {
        this._postMessage('connect_resource_bound', data);
    },

    _onWidgetUnavailable() {
        this._postMessage('connect_bind_promo_unavailable');
    },

    _onWindowMessage(windowEvent) {
        const data = windowEvent.data;
        const origin = windowEvent.origin;

        if (!Url.isAllowedIframeOrigin(origin) || !data || data.message !== 'connect_resource_response') {
            return;
        }

        this._stopListenPong();

        const requestData = {
            service: {
                slug: data.service_slug,
                resource: {
                    id: data.resource_id,
                    relations: data.relations,
                },
            },
        };

        Promise.all([
            OrganizationActions.getOrganizationsToBind(requestData),
            OrganizationActions.bindWithResource(requestData, { 'dry-run': 1 }),
        ])
            .then(([orgsToBind, canBindNewOrg]) => {
                let organizations = [];

                if (!orgsToBind.errors) {
                    organizations = orgsToBind.organizations;
                }

                // Не добавляю в список новую организацию, если ее нельзя создать
                // чтобы она не выводилась в селекте забизейбленной
                if (!canBindNewOrg.errors) {
                    organizations.push({
                        org_id: '*',
                        binding_available: true,
                    });
                }

                this.setState({
                    enabled: true,
                    relations: data.relations,
                    resourceId: data.resource_id,
                    serviceSlug: data.service_slug,
                    organizations,
                    origin,
                }, () => {
                    this._postSize();
                });

                this._sizeUpdateInterval = setInterval(this._onChangeSize, 300);
            })
            .catch(this._onWidgetUnavailable);
    },

    _setWidgetRef(widget) {
        this._widget = widget;
    },

    _getWidgetRef() {
        return this._widget;
    },

    render() {
        const { enabled, relations, resourceId, serviceSlug, organizations } = this.state;

        if (enabled) {
            return (
                <div className="bind-widget-page">
                    <BindWidget
                        ref={this._setWidgetRef}
                        onCancel={this._onCancel}
                        onSend={this._onSend}
                        relations={relations}
                        resourceId={resourceId}
                        serviceSlug={serviceSlug}
                        organizations={organizations}
                    />
                </div>
            );
        }

        return null;
    },

});

export default BindWidgetLayout;
