import React from 'react';
import { block } from 'bem-cn';
import { BalanceStore, PricingStore } from 'lib2/stores';
import openUrl from 'lib2/openUrl';
import isAllowedIframeOrigin from 'lib2/isAllowedIframeOrigin';
import directory from 'api2/directory';
import LegacySidebar from 'components2/LegacySidebar';
import SpinOverlay from 'components2/SpinOverlay';
import CreateContractForm from 'components2/CreateContractForm';
import './index.css';

const b = block('create-contract-page');

function openSourceUrl(isContractCreated) {
    const { searchParams } = new URL(window.location.href);
    const retpath = searchParams.get('retpath');

    if (!isContractCreated) {
        return openUrl(new URL('/portal/home?has_contract=false', window.location.origin).href);
    }

    if (retpath) {
        return openUrl(new URL(retpath, window.location.origin).href);
    }

    return openUrl('/portal/balance');
}

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

        this.state = {
            busy: true,
        };

        this._init = this._init.bind(this);
        this._updateSize = this._updateSize.bind(this);

        this._onBalanceStoreChange = this._onBalanceStoreChange.bind(this);
        this._onContractSubmit = this._onContractSubmit.bind(this);
    }

    componentDidMount() {
        this._onBalanceStoreChange();
        this._balanceStoreListener = BalanceStore.onChange(this._onBalanceStoreChange);

        this._update();

        if (this.props.asIframe) {
            window.addEventListener('message', ({ data, origin }) => {
                if (!data || !isAllowedIframeOrigin(origin)) {
                    return;
                }

                if (typeof data === 'object' && ['pong', 'props'].includes(data.message)) {
                    const { title, description, style, helpUrl, offerUrl, footnote } = data;

                    this.setState({
                        title,
                        description,
                        style,
                        helpUrl,
                        offerUrl,
                        footnote,
                    });
                }

                if (data === 'pong' || data.message === 'pong') {
                    this._targetOrigin = origin;
                    this._updateSize(true);
                }
            });

            window.parent.postMessage('ping', '*');
        }
    }

    componentWillUnmount() {
        this._unmounted = true;
        this._balanceStoreListener.remove();

        clearInterval(this._sizeTracker);
    }

    _onBalanceStoreChange() {
        this.setState({
            hasContract: BalanceStore.get('has_contract'),
        });
    }

    _onContractSubmit(isContractCreated) {
        if (this.props.asIframe) {
            this._targetOrigin && window.parent.postMessage({
                type: 'submit',
                isContractCreated,
            }, this._targetOrigin);

            return;
        }

        openSourceUrl(isContractCreated);
    }

    _updateSize(forceUpdate) {
        if (!this._element) {
            return;
        }

        let { offsetWidth, offsetHeight } = this._element;

        if (forceUpdate || this._width !== offsetWidth || this._height !== offsetHeight) {
            this._targetOrigin && window.parent.postMessage({
                type: 'size',
                width: offsetWidth,
                height: offsetHeight,
            }, this._targetOrigin);

            this._width = offsetWidth;
            this._height = offsetHeight;
        }
    }

    _init(element) {
        if (this.props.asIframe && element && !this._element) {
            this._element = element;
            this._sizeTracker = setInterval(() => this._updateSize(), 300);
        }
    }

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

        Promise
            .all([
                directory.send('GET', '/v11/subscription/'),
                directory.send('GET', '/v11/subscription/pricing/'),
                directory.send('GET', '/v11/subscription/persons/'),
            ])
            .then(([balance, pricing, persons]) => {
                if (balance.ok) {
                    BalanceStore.mergeState(balance.body);
                }

                if (pricing.ok) {
                    PricingStore.mergeState(pricing.body);
                }

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

    render() {
        const { busy, persons, title, description, style, helpUrl, offerUrl, footnote } = this.state;

        return (
            <React.Fragment>
                {style && <style className={b('widget-style')}>{style}</style>}
                <div
                    className={b({}).mix(this.props.cls)}
                    ref={this._init}
                >
                    {!this.props.asIframe && <LegacySidebar />}
                    <div className={b('content')}>
                        {busy ? (
                            <SpinOverlay
                                progress
                                size="m"
                                position="center"
                            />
                        ) : (
                            <CreateContractForm
                                persons={persons}
                                title={title}
                                description={description}
                                helpUrl={helpUrl}
                                offerUrl={offerUrl}
                                footnote={footnote}
                                onSubmit={this._onContractSubmit}
                            />
                        )}
                    </div>
                </div>
            </React.Fragment>
        );
    }
}
