import omit from 'lodash/omit';
import React from 'react';
import { block } from 'bem-cn';
import { Tooltip } from 'lego-on-react';

import './index.css';

const b = block('tooltip-box');

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

        this.state = {
            visible: this.props.initialVisible,
        };

        this._init = this._init.bind(this);
        this._showTooltip = this._showTooltip.bind(this);
        this._hideTooltip = this._hideTooltip.bind(this);
        this._toggleTooltip = this._toggleTooltip.bind(this);
        this._getInteractions = this._getInteractions.bind(this);
        this._onTooltipOutsideClick = this._onTooltipOutsideClick.bind(this);
    }

    componentDidMount() {
        this._mounted = true;

        window.addEventListener('scroll', () => {
            this._hideTooltip();
        });

        window.addEventListener('scrollarea-scroll', () => {
            this._hideTooltip();
        });
    }

    componentWillUnmount() {
        this._mounted = false;
    }

    _showTooltip() {
        clearTimeout(this._hideTimer);

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

    _hideTooltip() {
        if (this.props.hideDelay) {
            this._hideTimer = setTimeout(() => {
                if (this._mounted) {
                    this.setState({
                        visible: false,
                    });
                }
            }, this.props.hideDelay);

            return;
        }

        if (this._mounted) {
            this.setState({
                visible: false,
            });
        }
    }

    _toggleTooltip() {
        this.setState({
            visible: !this.state.visible,
        });
    }

    _init(element) {
        if (!this.state.anchor) {
            this.setState({
                anchor: element,
            });
        }
    }

    _getInteractions() {
        if (this.props.interaction === 'click') {
            return {
                onClick: this._toggleTooltip,
            };
        }

        return {
            onMouseEnter: this._showTooltip,
            onMouseLeave: this._hideTooltip,
        };
    }

    _getTooltipInteractions() {
        if (this.props.interaction !== 'click' && this.props.noHideOnTooltip) {
            return {
                onMouseOver: this._showTooltip,
                onMouseLeave: this._hideTooltip,
            };
        }

        return {};
    }

    _onTooltipOutsideClick() {
        this.setState({
            visible: false,
        });
    }

    render() {
        const { state, props } = this;

        if (!props.tip && !props.htmlTip) {
            return <span className={b()}>{props.children}</span>;
        }

        const tooltipProps = omit(props, [
            'cls',
            'children',
            'interaction',
            'hideDelay',
            'noHideOnTooltip',
            'tip',
            'initialVisible',
        ]);

        return (
            <span
                className={b({ clickable: props.interaction === 'click' }).mix(props.cls)}
                {...this._getInteractions()}
                ref={this._init}
            >
                {props.children}
                {state.anchor &&
                <Tooltip
                    {...tooltipProps}
                    visible={state.visible}
                    anchor={state.anchor}
                    onOutsideClick={this._onTooltipOutsideClick}
                    {...this._getTooltipInteractions()}
                >
                    {props.htmlTip ?
                        <span dangerouslySetInnerHTML={{ __html: props.htmlTip }} /> :
                        props.tip}
                </Tooltip>}
            </span>
        );
    }
}
