import Vue from 'vue/dist/vue'
import BrickPreviewer from './previewerTools';
import IframeFocusTracer from "../util/IframeFocusTracer";
import EventBus from "../util/EventBus";
import EventTypes from "../util/EventTypes";
import ScrollHelper from "../util/ScrollHelper";

Vue.component('previewer-iframe', {
    delimiters: ['<<', '>>'],
    props: {
        previewer: {default: null},
        builder: {default: null},
        url: {default: null},
        viewport: {default: null},
    },
    data: function () {
        return {
            brickPreviewerTools: null,

            iframeUrl: {default: null},
            iframeUrlGeneration: 0,
            iframeHeight: {default: 600},

            toolbarBrickBounds: null,
            toolbarBrick: null,
            triggerDelayMouseoutTimeout: null,

            // focus state
            toolbarIsFocused: false,
            iframeBrickIsFocused: false,
            // focused elements
            focusedIframeBrickEl: null,// html el
            focusedBrick: null,// tree leaf
            changeFocusTimeoutHandle: null,

            boundsFocusDrawer: null,

            // disable toolbar rendering
            toolbarIsEnabled: true,
        };
    },
    methods: {
        getIframeEl() {
            return this.$el.querySelector(':scope iframe');
        },
        addIframeListeners() {
            var iframe = this.getIframeEl();
            if (iframe === null) {
                this.$nextTick(() => {
                    this.addIframeListeners();
                });

                return;
            }

            var doc = iframe.contentWindow.document;
            iframe.contentWindow.addEventListener('DOMContentLoaded', () => {
                this.iframeHeight = ScrollHelper.getScrollHeight(doc);
            });

            // listen for all brick mouse moves
            var selector = '[data-brick-id]:not(.section):not(.row):not(.col)';
            var bricks = doc.querySelectorAll(selector);
            bricks.forEach((el) => {
                el.addEventListener('mouseenter', this.iframeMouseenter);
                el.addEventListener('mouseleave', this.iframeMouseleave);
            });

            // UI refresh on scroll (big performance impact, delayed for now)
            // var scrollTimeoutHandle = null;
            // var observer = new IntersectionObserver(() => {
            //     if (scrollTimeoutHandle) {
            //         clearTimeout(scrollTimeoutHandle);
            //     }
            //     scrollTimeoutHandle = setTimeout(() => {
            //         this.updateUI();
            //     }, 50);
            // });
            // observer.observe(doc.querySelector('body'));
        },
        iframeMouseenter(e) {
            if (this.changeFocusTimeoutHandle) {
                clearTimeout(this.changeFocusTimeoutHandle);
            }
            this.focusedIframeBrickEl = e.target;
            this.focusedBrick = this.builder.getBrick(this.focusedIframeBrickEl.attributes['data-brick-id'].value);
            this.iframeBrickIsFocused = true;
            this.updateUI();
            e.stopPropagation();
        },
        iframeMouseleave(e) {
            this.delayDiscardFocus();
            this.updateUI();
            e.stopPropagation();
        },
        toolbarMouseenter(e) {
            this.toolbarIsFocused = true;
            if (this.changeFocusTimeoutHandle) {
                clearTimeout(this.changeFocusTimeoutHandle);
            }
            this.updateUI();
        },
        toolbarMouseleave(e) {
            this.delayDiscardFocus();
            this.updateUI();
        },
        delayDiscardFocus() {
            if (this.toolbarIsFocused || this.iframeBrickIsFocused) {
                return;
            }
            clearTimeout(this.changeFocusTimeoutHandle);
            this.changeFocusTimeoutHandle = setTimeout(() => {
                this.toolbarIsFocused = false;
                this.iframeBrickIsFocused = false;
                this.focusedIframeBrickEl = null;
                this.changeFocusTimeoutHandle = null;
                this.updateUI();
            }, 1000);
        },
        updateUI() {
            if (!this.focusedIframeBrickEl) {
                this.boundsFocusDrawer.hide(this.getIframeEl())
                return;
            }

            var outlineBounds = this.boundsFocusDrawer.draw(this.getIframeEl(), this.focusedIframeBrickEl);
            this.toolbarBrickBounds = this.translateFocusBoundsToFixedPosition(outlineBounds);
        },
        translateFocusBoundsToFixedPosition(outlineBounds) {
            var iframe = this.getIframeEl();
            var iframeElBounds = iframe.getBoundingClientRect();
            outlineBounds.top = Math.max(outlineBounds.top + iframeElBounds.top, iframeElBounds.top + 34);
            outlineBounds.left = outlineBounds.left + iframeElBounds.left;

            return outlineBounds;
        },
        resetFocus() {
            this.focusedIframeBrickEl = null;
            this.focusedBrick = null;
        },
        handleUpdated() {
            this.resetFocus();
            // reload iframe after brick update
            this.reloadIframe();
        },
        reloadIframe() {
            var iframe = this.getIframeEl()
            var currentUrl = '' + this.iframeUrl;

            var fakeHost = 'https://fakehost.local';
            if (currentUrl.indexOf('http://') !== 0 && currentUrl.indexOf('https://') !== 0) {
                currentUrl = fakeHost + currentUrl;
            }
            var url = new URL(currentUrl);
            this.iframeUrlGeneration++;
            url.searchParams.set('iframeGeneration', this.iframeUrlGeneration);

            var urlString = url.toString().replace(fakeHost, '');
            this.iframeUrl = urlString;
        },
        iframeLoaded() {
            this.addIframeListeners();
        }
    },
    // just after creation
    created() {
        this.iframeUrl = this.url;
        this.triggerDelayMouseoutTimeout = this.delayDiscardFocus;
        this.boundsFocusDrawer = new IframeFocusTracer();
        EventBus.$on(EventTypes.BRICK_UPDATED, this.handleUpdated);
        EventBus.$on(EventTypes.PREVIEWER_VIEWPORT_CHANGE, this.resetFocus);
    },
    // after replacing $el
    mounted() {
        // this.$nextTick(() => {
        //     this.addIframeListeners();
        // });
    },
    // after update/re-render
    updated() {
        // this.$nextTick(() => {
        //     this.addIframeListeners();
        // });
    },
    computed: {
        iframeClasses() {
            var classes = {};
            classes[this.viewport] = true;
            return classes;
        }
    },
    template: `
      <div
          class="previewer-iframe"
          :class="iframeClasses"
      >
        <div v-if="typeof iframeUrl !== 'string'"
             v-html="builder.context.loader"
        ></div>
        <iframe
            v-else
            class="preview-iframe"
            :class="iframeClasses"
            frameborder="0"
            :src="iframeUrl"
            :style="{height: iframeHeight + 'px'}"
            @load="iframeLoaded"
        ></iframe>
        <span
            class="url-inline-text badge badge-secondary"
            v-html="iframeUrl"></span>
        <previewer-toolbar
            :brick-bounds="toolbarBrickBounds"
            :focused-brick="focusedBrick"
            :trigger-delay-mouseout-timeout="triggerDelayMouseoutTimeout"
            @mouseenter="toolbarMouseenter"
            @mouseover="toolbarMouseenter"
            @mouseleave="toolbarMouseleave"
        ></previewer-toolbar>
      </div>
    `,
});
