const DomOutline = function (options) {
    options = options || {};

    const pub = {};
    const self = {
        opts: {
            namespace: options.namespace || 'DomOutline',
            borderWidth: options.borderWidth || 2,
            onClick: options.onClick || false,
            filter: options.filter || false
        },
        keyCodes: {
            BACKSPACE: 8,
            ESC: 27,
            DELETE: 46
        },
        active: false,
        initialized: false,
        elements: {}
    };

    function writeStylesheet(css) {
        var element = document.createElement('style');
        element.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(element);

        if (element.styleSheet) {
            element.styleSheet.cssText = css; // IE
        } else {
            element.innerHTML = css; // Non-IE
        }
    }

    function initStylesheet() {
        if (self.initialized !== true) {
            var css = `
                .${self.opts.namespace}_active iframe{
                pointer-events: none;
                }
                .${self.opts.namespace}{
                    background: #09c;
                    position: absolute;
                    z-index: 1000000;
                }
                
                .${self.opts.namespace}_label {
                    background: #09c;
                    border-radius: 2px;
                    color: #fff;
                    font: bold 12px/12px Helvetica, sans-serif;
                    padding: 4px 6px;
                    position: absolute;
                    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
                    z-index: 1000001;
                }`;

            writeStylesheet(css);
            self.initialized = true;
        }
    }

    function createOutlineElements() {
        self.elements.label = jQuery('<div></div>').addClass(self.opts.namespace + '_label').appendTo('body');
    }

    function removeOutlineElements() {
        jQuery.each(self.elements, function (name, element) {
            element.remove();
        });
    }

    function compileLabelText(element, width, height) {
        var label = element.tagName.toLowerCase();
        if (element.id) {
            label += '#' + element.id;
        }
        if (element.className) {
            label += ('.' + jQuery.trim(element.className).replace(/ /g, '.')).replace(/\.\.+/g, '.');
        }

        //return label + ' (' + Math.round(width) + 'x' + Math.round(height) + ')';

        return label;
    }

    function getScrollTop() {
        if (!self.elements.window) {
            self.elements.window = jQuery(window);
        }
        return self.elements.window.scrollTop();
    }

    function shouldIgnore(e) {

        // const selector = unique(e.target, {
        //     excludeRegex: RegExp('hide-anything-hidden')
        // });

        // if (Object.keys(hideAnything.selectors).includes(selector)) {
        //     return true;
        // }


        if (typeof e.target.className === "string" && e.target.className.indexOf(self.opts.namespace) !== -1) {
            return true;
        }

        if (jQuery(e.target).closest('.dracula-ignore').length > 0) {
            return true;
        }

        return false;
    }

    function updateOutlinePosition(e) {

        if (shouldIgnore(e)) {
            removeOutlineElements();
            return;
        } else {
            if (!jQuery('.DomOutline_label').length) {
                createOutlineElements();
            }
        }

        let isBackgroundImage = false;

        if (self.opts.filter) {

            if ('img' === self.opts.filter) {
                isBackgroundImage = 'none' !== jQuery(e.target).css('background-image');
                if (e.target.tagName !== 'IMG' && !isBackgroundImage) {
                    return;
                }
            } else if ('video,iframe' === self.opts.filter) {
                const hasIframe = jQuery(e.target).find('>iframe').length > 0;

                if (e.target.tagName !== 'VIDEO' && !hasIframe) {
                    return;
                }

                //if iframe and not youtube or vimeo then return
                if (hasIframe) {
                    const src = jQuery(e.target).find('iframe').attr('src');

                    const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/gi;
                    const isYoutube = src.match(youtubeRegex);

                    const vimeoRegex = /^(https?:\/\/)?(((player\.)?vimeo\.com\/video\/)|(vimeo\.com\/))([0-9]+)/gi;
                    const isVimeo = src.match(vimeoRegex);

                    const dailymotionRegex = /^(https?:\/\/)?(www\.)?(dailymotion\.com)\/.+$/gi;
                    const isDailymotion = src.match(dailymotionRegex);

                    if (!isYoutube && !isVimeo && !isDailymotion) {
                        return;
                    }

                }
            } else if (!jQuery(e.target).is(self.opts.filter)) {
                return;
            }
        }

        pub.element = e.target;

        const b = self.opts.borderWidth;
        const scroll_top = getScrollTop();
        const pos = pub.element.getBoundingClientRect();
        const top = pos.top + scroll_top;
        const {width, height} = pos;

        var label = compileLabelText(pub.element, pos.width, pos.height) + '<span class="DomOutline_border"></span>';
        //let label = `<i class="dashicons dashicons-hidden"></i> <span class="label-text label-exclude">${wp.i18n.__('Click to exclude', 'dracula-dark-mode')}</span> <span class="DomOutline_border"></span>`;

        //if filter only image then change label
        if (self.opts.filter === 'img') {
            label = `<span class="label-text label-select-image">${isBackgroundImage ? wp.i18n.__('Select Background Image', 'dracula-dark-mode') : wp.i18n.__('Select Image', 'dracula-dark-mode')}</span> <span class="DomOutline_border"></span>`;
        }

        if (self.opts.filter === 'video,iframe') {
            label = `<span class="label-text label-select-video">${wp.i18n.__('Select Video', 'dracula-dark-mode')}</span> <span class="DomOutline_border"></span>`;
        }

        const label_top = Math.max(0, top - 17 - b, scroll_top);
        const label_left = Math.max(0, pos.left - b);

        self.elements.label.css({top: label_top, left: label_left}).html(label);
        jQuery('.DomOutline_border').css({width, height});
    }

    function stopOnEscape(e) {
        if (e.keyCode === self.keyCodes.ESC || e.keyCode === self.keyCodes.BACKSPACE || e.keyCode === self.keyCodes.DELETE) {
            pub.stop();
        }

        return false;
    }

    function clickHandler(e) {
        e.preventDefault();
        e.stopPropagation();

        pub.stop();
        self.opts.onClick(e, pub.element);

        return false;
    }

    pub.start = function () {
        jQuery('body').addClass(self.opts.namespace + '_active');

        initStylesheet();
        if (self.active !== true) {
            self.active = true;
            createOutlineElements();

            jQuery('body').on('mousemove.' + self.opts.namespace, updateOutlinePosition);
            jQuery('body').on('keyup.' + self.opts.namespace, stopOnEscape);

            if (self.opts.onClick) {
                // setTimeout(function () {

                jQuery('body').on('click.' + self.opts.namespace, function (e) {
                    if (shouldIgnore(e)) {
                        return;
                    }

                    if (self.opts.filter) {
                        if ('img' === self.opts.filter) {
                            if (e.target.tagName !== 'IMG' && 'none' === jQuery(e.target).css('background-image')) {
                                return false;
                            }
                        } else if ('video,iframe' === self.opts.filter) {
                            //jquery check if element has a direct child iframe
                            const hasIframe = jQuery(e.target).find('>iframe').length

                            if (e.target.tagName !== 'VIDEO' && !hasIframe) {
                                return;
                            }

                            if (hasIframe) {
                                const src = jQuery(e.target).find('iframe').attr('src');

                                const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/gi;
                                const isYoutube = src.match(youtubeRegex);

                                const vimeoRegex = /^(https?:\/\/)?(((player\.)?vimeo\.com\/video\/)|(vimeo\.com\/))([0-9]+)/gi;
                                const isVimeo = src.match(vimeoRegex);

                                const dailymotionRegex = /^(https?:\/\/)?(www\.)?(dailymotion\.com)\/.+$/gi;
                                const isDailymotion = src.match(dailymotionRegex);

                                if (!isYoutube && !isVimeo && !isDailymotion) {
                                    return;
                                }

                            }
                        } else if (!jQuery(e.target).is(self.opts.filter)) {
                            return false;
                        }
                    }

                    clickHandler.call(this, e);
                });


                // }, 10);
            }
        }
    };

    pub.stop = function () {
        jQuery('body').removeClass(self.opts.namespace + '_active');

        self.active = false;
        removeOutlineElements();
        jQuery('body').off('mousemove.' + self.opts.namespace)
            .off('keyup.' + self.opts.namespace)
            .off('click.' + self.opts.namespace);
    };

    return pub;
};

export default DomOutline;