import EventBus from "../util/EventBus";
import EventTypes from "../util/EventTypes";

var BrickPreviewer = function () {
    return {
        iframe: null,
        previewerComp: null,
        focused: null,
        focusedBar: null,
        targetBrick: null,
        targetTopPosition: null,
        reloadIframeInterval: null,
        mouseoutTimeoutHandle: null,
        init: function (previewerComp, iframe) {
            this.previewerComp = previewerComp;
            this.previewerComp.triggerDelayMouseoutTimeout = this.delayMouseoutTimeout;
            this.iframe = iframe;

            var self = this;

            var mode = 'default'; // add possibility to toggle default/all
            var selectors = {
                default: '[data-brick-id]:not(.section):not(.row):not(.col)',
                all: '[data-brick-id]',
            }

            this.iframe.contentWindow.addEventListener('DOMContentLoaded', function () {
                // TODO: not fuckin rendering till visible on screen, so no height !
                var doc = self.iframe.contentWindow.document;

                var iframeScrollHeight = Math.max.apply(null, [
                    doc.querySelector('html').scrollHeight,
                    doc.querySelector('body').scrollHeight
                ]);
                self.iframe.style.height = iframeScrollHeight + 'px';
            })

            this.iframe.addEventListener('load', function (e) {
                var selector = selectors[mode];
                var doc = self.iframe.contentWindow.document;
                doc.querySelectorAll(selector).forEach(function (el) {
                    el.addEventListener('mouseenter', self.brickPreviewMouseEnter.bind(self));
                    el.addEventListener('mouseleave', self.brickPreviewMouseLeave.bind(self));
                });

                if (self.targetTopPosition) {
                    doc.querySelector('html').scrollTo({
                        top: self.targetTopPosition,
                        behavior: 'smooth'
                    });
                }
            });
            // this.iframe.addEventListener('mouseleave', function (e) {
            //     if (e.target !== this.iframe) {
            //         return;
            //     }
            //     this.focused = null;
            //     this.focusedBar = null;
            //     this.refreshInterface();
            // }.bind(this));
        },
        reloadIframe: function () {
            // TODO: retrieve scroll height before reload and
            if (typeof this.targetBrick != 'undefined'
                && this.iframe.contentDocument
                && this.iframe.contentDocument.querySelector('html')
                && this.iframe.contentDocument.querySelector('body')
            ) {
                this.targetTopPosition = Math.max(
                    this.iframe.contentDocument.querySelector('html').scrollTop,
                    this.iframe.contentDocument.querySelector('body').scrollTop
                );
            }

            if (this.iframe.offsetParent === null) {
                // iframe is hidden, use interval to reload when iframe is visible again
                var self = this;
                if (this.reloadIframeInterval) {
                    clearInterval(this.reloadIframeInterval);
                }
                this.reloadIframeInterval = setInterval(function () {
                    if (self.iframe.offsetParent === null) {
                        return;
                    }
                    clearInterval(self.reloadIframeInterval);
                    self.iframe.src = '' + self.iframe.src;
                }, 200);
            } else {
                // simply reassign src to force reload
                this.iframe.src = '' + this.iframe.src;
            }
        },
        brickPreviewMouseEnter (e) {
            if (e.target.classList.contains('.brick-edit-bar') || e.target.closest('.brick-edit-bar') !== null) {
                this.focusedBar = e.target;
                return;
            }
            this.focused = e.target;

            e.stopPropagation();
            this.refreshInterface();
        },
        brickPreviewMouseLeave(e) {
            if (this.focusedBar !== null) {
                return;
            }

            if (e.target.classList.contains('.brick-edit-bar') || e.target.closest('.brick-edit-bar') !== null) {
                this.delayMouseoutTimeout();

                return;
            }

            this.delayMouseoutTimeout();
            e.stopPropagation();
            this.refreshInterface();
        },
        delayMouseoutTimeout() {
            if (this.mouseoutTimeoutHandle) {
                clearTimeout(this.mouseoutTimeoutHandle);
            }
            this.mouseoutTimeoutHandle = setTimeout(() => {
                this.focusedBar = null;
                this.focused = null;

                this.previewerComp.updatePreviewBounds({
                    bounds: null,
                    brick: null,
                });
            }, 1000);
        },
        refreshInterface: function () {
            var doc = this.iframe.contentWindow.document;

            var iframeScrollTop = Math.max.apply(null, [
                doc.querySelector('html').scrollTop,
                doc.querySelector('body').scrollTop
            ]);
            // var bar = this.resolveActionBar();
            var outline = this.resolveOutline();

            if (this.focused === null) {
                // bar.style.display = 'none';
                outline.style.display = 'none';
                return;
            } else {
                // bar.style.display = 'block';
                outline.style.display = 'block';
            }

            var relatedBrickId = this.focused.attributes['data-brick-id'].value;
            var relatedBrick = document.querySelector('.brick-builder .root-brick .brick[data-brick-id="' + relatedBrickId + '"]');
            this.builderBrickReference = relatedBrick;

            var bodyRect = doc.body.getBoundingClientRect();
            var iframeRect = this.iframe.getBoundingClientRect();
            var focusedRect = this.focused.getBoundingClientRect();
            var offset = {
                top: focusedRect.top - bodyRect.top,
                left: focusedRect.left - bodyRect.left,
            };
            // var barStyle = bar.style;
            // barStyle.top = offset.top - 40 + 'px';
            // barStyle.left = offset.left - 5/* border width */ + 'px';

            var outlineBounds = {
                top: offset.top - 5,
                left: offset.left - 5,
                height: focusedRect.height + 10,
                width: focusedRect.width + 10,
            };

            var outlineStyle = outline.style;
            outlineStyle.top = outlineBounds.top + 'px';
            outlineStyle.left = outlineBounds.left + 'px';
            outlineStyle.height = outlineBounds.height + 'px';
            outlineStyle.width = outlineBounds.width + 'px';

            var outsideIframeBrickBounds = {
                top: Math.max(outlineBounds.top + iframeRect.y - iframeScrollTop, iframeRect.y),
                left: outlineBounds.left + iframeRect.x,
                height: outlineBounds.height,
                width: outlineBounds.width,
            };

            this.previewerComp.updatePreviewBounds({
                bounds: outsideIframeBrickBounds,
                brick: this.previewerComp.builder.getBrick(relatedBrickId),
            });
        },
        resolveOutline: function () {
            var doc = this.iframe.contentWindow.document;

            var existant = doc.querySelector('.brick-edit-bar-outline');
            if (existant !== null) {
                return existant;
            }

            var outline = doc.createElement('div');

            outline.classList.add('brick-edit-bar-outline');
            outline.style.position = 'absolute';
            outline.style.zIndex = '999';
            outline.style.border = '5px solid rgba(78,115,223,.25)';
            outline.style.background = 'rgba(78,115,223,.25)';
            outline.style.touchAction = 'none';
            outline.style.pointerEvents = 'none';
            outline.style.borderRadius = '5px';

            doc.body.appendChild(outline);

            return outline;
        },
    }
};


export default BrickPreviewer;
