import baseTool from '../../util/baseTool';
import 'intersection-observer';
import { tpl } from './toastTpl'
const Tooltips = (($) => {
    window._eldTooltipsInstanceNum = window._eldTooltipsInstanceNum || 0;
    const TPL = tpl,
        DefaultConfig = {
            direction: 'right',
            tpl: TPL,
            selector: '.tooltips',
            titleAttr: 'data-title',
            contentAttr: 'data-content',
            directionAttr: 'data-direction',
            title: '',
            content: ''
        };
    class Tooltips {
        static directionMap = {
            'left': 'right',
            'right': 'left',
            'top': 'bottom',
            'bottom': 'top',
        }
        constructor(config) {
            this._config = this._getConfig(config);
            let self = this;
            $(this._config.selector).attr('data-tooltips', '');
            $(this._config.selector).each(function() {
                let $this = $(this);
                let config = self._config;
                let title = typeof $this.attr(config.titleAttr) === 'string' ? $this.attr(config.titleAttr) : config.title,
                    content = typeof $this.attr(config.contentAttr) === 'string' ? $this.attr(config.contentAttr) : config.content,
                    direction = typeof $this.attr(config.directionAttr) === 'string' ? $this.attr(config.directionAttr) : config.direction;
                let attr = {};
                attr[config.titleAttr] = title;
                attr[config.contentAttr] = content;
                attr[config.directionAttr] = direction;
                $this.attr(attr);
            })
            
            if (window._eldTooltipsInstanceNum === 0) {
                Tooltips._addEvent.bind(this)();
            }
            window._eldTooltipsInstanceNum++;
        }
        
        _getConfig(config) {
            return $.extend({}, DefaultConfig, config);
        }
        
        static position(node, tooltips, config) {
            let direction = config.direction;
            let $Tooltips = $(tooltips);
            let el = node,
                $el = $(node);
            let toastWidth = $Tooltips[0].offsetWidth,
                toastHeight = $Tooltips[0].offsetHeight;
            let offsetTop = $el.offset().top,
                offsetLeft = $el.offset().left;
            let eleWidth = el.offsetWidth,
                eleHeight = el.offsetHeight;
            switchDirection(direction);
            let intersectionObserver = new IntersectionObserver((entries) => {
                const percent = entries[0].intersectionRatio;
                if (percent < 1) {
                    switchDirection(Tooltips.directionMap[direction] || direction)
                }
                intersectionObserver.unobserve($Tooltips[0]);
                intersectionObserver.disconnect();
            });
            intersectionObserver.observe($Tooltips[0]);
            function switchDirection(direction) {
                let left = 0;
                let top = 0;
                $Tooltips.removeClass(`cd-${Tooltips.directionMap[direction]}`).addClass(`cd-${direction}`);
                switch (direction) {
                    case 'left':
                        left = offsetLeft - toastWidth;
                        top = offsetTop - toastHeight / 2 + eleHeight / 2;
                        break;
                    case 'right':
                        left = offsetLeft + eleWidth;
                        top = offsetTop - toastHeight / 2 + eleHeight / 2;
                        break;
                    case 'top':
                        left = offsetLeft - toastWidth / 2 + eleWidth / 2;
                        top = offsetTop - toastHeight;
                        break;
                    case 'bottom':
                        left = offsetLeft - toastWidth / 2 + eleWidth / 2;
                        top = offsetTop + eleHeight;
                        break;
                    case 'right-top':
                        left = offsetLeft;
                        top = offsetTop - toastHeight;
                        break;
                    case 'left-top':
                        left = offsetLeft - toastWidth + eleWidth;
                        top = offsetTop - toastHeight;
                        break;
                    case 'right-bottom':
                        left = offsetLeft;
                        top = offsetTop + eleHeight;
                        break;
                    case 'left-bottom':
                        left = offsetLeft - toastWidth + eleWidth;
                        top = offsetTop + eleHeight;
                        break;
                }
                $Tooltips.css({
                    left: left + 'px',
                    top: top + 'px'
                })
            }
        }
        static isHover;
        
        static _addEvent() {
            let config = this._config;
            let _this = this;
            $(document)
                .off('mouseenter.Tooltips')
                .off('mouseleave.Tooltips')
                .on('mouseenter.Tooltips', '[data-tooltips]', mouseroverEvent)
                .on('mouseleave.Tooltips', '[data-tooltips]', function(e) {
                    if (this.$Tooltips) {
                        this.$Tooltips.isHover = false;
                        mouseoutEvent.call(this, e)
                    }
                });
            $(document)
                .on('mouseenter.Tooltips', '.J_EldTooltips', function() {
                    Tooltips.isHover = true;
                })
                .on('mouseleave.Tooltips', '.J_EldTooltips', function() {
                    Tooltips.isHover = false;
                })
            function mouseroverEvent() {
                let $this = $(this);
                let title = typeof $this.attr(config.titleAttr) === 'string' ? $this.attr(config.titleAttr) : DefaultConfig.title,
                    content = typeof $this.attr(config.contentAttr) === 'string' ? $this.attr(config.contentAttr) : DefaultConfig.content,
                    definedClass = $this.attr('data-definedClass') || ''; 
                let direction = $this.attr(config.directionAttr) ? $this.attr(config.directionAttr) : ($this.attr('data-direaction') ? $this.attr('data-direaction') : DefaultConfig.direction);
                let _config = $.extend(true, config, {
                    title,
                    content,
                    direction,
                    definedClass
                });
                if (!content) {
                    return;
                }
                if (this.$Tooltips) {
                    this.$Tooltips.remove();
                }
                let $Tooltips = $(template.render(_config.tpl, _config));
                $Tooltips.addClass(config.definedClass);
                this.$Tooltips = $Tooltips;
                $('body').append($Tooltips);
                $Tooltips.css('z-index', baseTool.getToolTipIndex());
                Tooltips.position(this, $Tooltips[0], _config);
                $Tooltips.addClass('show');
                $Tooltips.isHover = true;
            }
            function mouseoutEvent() {
                if ($(this).attr('data-can-hover') === 'true') {
                    setTimeout(() => {
                        close.call(this);
                    }, 300);
                } else {
                    close.bind(this)();
                }
                function close() {
                    if (Tooltips.isHover === true) {
                        mouseoutEvent.call(this);
                    } else if (this.$Tooltips && this.$Tooltips.isHover !== true) {
                        this.$Tooltips.removeClass('show');
                        this.$Tooltips.remove();
                    }
                }
            }
        }
        
        dispose() {
            $(document).off('mouseenter.Tooltips').off('mouseleave.Tooltips');
        }
    }
    return Tooltips;
})($);
export default Tooltips;