import {createApp} from 'vue'

const tocs = document.querySelectorAll('.webien-toc-widget-toc');

if (tocs) {
    tocs.forEach((el) => {
        const $app = createApp({
            name: "TOC widget " + el.dataset.unique,
            data() {
                return {
                    appReady: false,
                    title: 'TOC',
                    chapters: [],
                    doingScroll: false,
                    settings: window['webienTocSettings_' + el.dataset.unique],
                    narrow: {
                        open: false,
                        scrollPos: 0
                    },
                }
            },
            mixins: [],
            computed: {},
            watch: {},
            methods: {
                init() {

                    let app = this;

                    // Set dock offset from JS settings.
                    let root = document.documentElement;
                    if(root){
                        root.style.setProperty('--toc-dock-offset', app.settings.dockOffset);
                    }


                    this.searchChapters();


                    if (app.settings.dockContainer) {
                        // Use Waypoints to set sticky position
                        let sticky = new Waypoint.Sticky({
                            element: document.getElementById('webien-toc-widget-' + el.dataset.unique),
                            offset: app.settings.dockContainerOffset,
                        });
                    }

                    this.updateDockWidth();
                    window.onresize = function () {
                        app.updateDockWidth();
                    }

                    // Set breakpoint from settings
                    if (app.settings.breakpoint) {
                        let r = document.querySelector(':root');
                        r.style.setProperty('--toc-breakpoint', app.settings.breakpoint + 'px');
                    }

                },
                updateDockWidth() {
                    let root = document.documentElement;
                    let parent = el.closest('.sticky-wrapper');
                    if (parent) {
                        let width = parent.offsetWidth;
                        if (width < 1) {
                            let econ = parent.closest('.e-con');
                            if (econ) {
                                width = econ.offsetWidth;
                            }
                        }
                        root.style.setProperty('--toc-dock-width', width + 'px');
                    } else {
                        root.style.setProperty('--toc-dock-width', '100%');
                    }

                },
                searchChapters() {
                    let app = this;

                    let container = document.querySelector(this.settings.contentArea);
                    if (!container) return [];

                    let chapters = container.querySelectorAll(this.settings.tags.join());
                    if (!chapters) return [];


                    let tocOuter = document.getElementById('webien-toc-widget-' + el.dataset.unique);
                    let tocContainer = document.querySelector('#webien-toc-widget-' + el.dataset.unique + ' .standard-view');

                    if (!tocOuter || !tocContainer) return [];

                    // Check if widget is in an elementor sticky container
                    let inStickyContainer = false

                    // Wait for Elementor class
                    setTimeout(() => {
                        inStickyContainer = !!tocOuter.closest('.elementor-sticky');

                        // If Elementor stickyContainer is higher than viewport, cut it to viewport height so we can scroll it later
                        if (inStickyContainer) {
                            let stickyContainer = tocOuter.closest('.elementor-sticky');
                            let stickyContainerHeight = stickyContainer.clientHeight;
                            let availableHeight = window.innerHeight - stickyContainer.getBoundingClientRect().top;
                            if (stickyContainerHeight > availableHeight) {
                                stickyContainer.style.height = availableHeight + 'px';
                                stickyContainer.style.transition = "top 0.5s ease";
                            }
                        }

                    }, 1000);


                    let chapterLevels = [];
                    chapters.forEach((chapter, i) => {

                        // Skip if in blockquote
                        if (chapter.closest('blockquote')) return;

                        let tagName = chapter.tagName.toLowerCase().replace('h', '');
                        let level = parseInt(tagName);
                        chapterLevels.push(level);
                    });
                    // Check for lowest value in array
                    let minLevel = Math.min(...chapterLevels);


                    chapters.forEach((chapter, i) => {

                        // Skip if in blockquote
                        if (chapter.closest('blockquote')) return;

                        // Check if element has a ancestor with class .no-toc
                        if (this.settings.excludeArea !== '' && chapter.closest(this.settings.excludeArea) !== null) {
                            return;
                        }

                        // Set level
                        let level = chapterLevels[i] - minLevel + 1;

                        // Fallback to 1 if level is nan
                        if(isNaN(level) || !level){
                            level = 1;
                        }


                        // Create waypoint for each chapter
                        let waypoint = new Waypoint({
                            element: chapter,
                            handler: function (direction) {

                                let matchIndex = 0;
                                let chapterObject = app.chapters.find((item, index) => {
                                    matchIndex = index;
                                    return item.url === '#' + chapter.id;
                                });


                                // When scrolling up, activate the previous chapter when waypoint is reversed
                                if (direction === 'up' && matchIndex > 0) {
                                    chapterObject = app.chapters[matchIndex - 1];
                                }

                                if (chapterObject && !app.doingScroll) {
                                    app.chapters.forEach((item) => {
                                        item.active = false;
                                    });
                                    chapterObject.active = true;

                                    // If toc container is higher than viewport, we need to scroll it as well
                                    if (tocOuter) {
                                        if (tocOuter.clientHeight < (window.innerHeight - parseFloat(app.settings.dockOffset))) {
                                            // Smaller than viewport, no need to scroll
                                            return;
                                        }
                                    }

                                    // Check inner scroll of TOC
                                    if (tocOuter) {
                                        let activeChapter = tocContainer.querySelector('.chapters button.active');
                                        if (activeChapter) {
                                            let offset = activeChapter.offsetTop;
                                            let compareValue = (tocOuter.clientHeight - parseFloat(app.settings.dockOffset)) * 0.6; // Trigger with 25% offset

                                            //console.log(offset, tocOuter.clientHeight, compareValue);

                                            if (inStickyContainer) {
                                                let stickyContainer = tocOuter.closest('.elementor-sticky');
                                                let settings = JSON.parse(stickyContainer.dataset.settings);
                                                let initialOffset = parseFloat(settings.sticky_offset);

                                                compareValue = (stickyContainer.clientHeight - initialOffset) * 0.4; // Trigger with 25% offset

                                                if (offset > compareValue) {
                                                    // Set scroll position for container
                                                    stickyContainer.style.top = ((offset - compareValue) * -1) - (compareValue * 0.4) + 'px'; // 50% extra for beter visibility
                                                } else {
                                                    // Reset scroll position
                                                    stickyContainer.style.top = initialOffset + 'px';
                                                }
                                            }

                                            if (!inStickyContainer) {
                                                compareValue = (tocOuter.clientHeight - parseFloat(app.settings.dockOffset)) * 0.6; // Trigger with 25% offset

                                                if (offset > compareValue) {
                                                    // Set scroll position for container
                                                    tocOuter.style.top = ((offset - compareValue) * -1) - (compareValue * 0.4) + 'px'; // 50% extra for beter visibility
                                                } else {
                                                    // Reset scroll position
                                                    tocOuter.style.top = app.settings.dockOffset;
                                                }
                                            }

                                        }
                                    }

                                }
                            },
                            offset: this.settings.triggerOffset
                        });


                        // Add id to headings for anchor links
                        if (!chapter.id) {
                            let id = this.settings.hashPrefix + chapter.innerText.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase();
                            // If the ID do not start with a character, insert one for valid HTML
                            if (!id.match(/^[a-zA-Z]/)) {
                                id = 'tocItem-' + id;
                            }

                            chapter.id = id;
                        }


                        chapter.classList.add('chapter-heading');

                        /*
                        // Add inline link icon
                        let anchor = document.createElement('span');
                        anchor.classList.add('anchor');
                        anchor.innerHTML = '&nbsp;';

                        // Make sure not to duplicate the anchor
                        if (chapter.querySelector('.anchor') === null) {
                            chapter.appendChild(anchor);
                        }

                         */

                        // Listen for click on chapter
                        chapter.addEventListener('click', (e) => {
                            e.preventDefault();

                            this.scrollToChapter({
                                url: '#' + chapter.id
                            }, true);

                        });


                        let chapterObject = {
                            title: chapter.innerText,
                            url: '#' + chapter.id,
                            children: [],
                            level: level
                        };
                        app.chapters.push(chapterObject);
                    });


                    // Make sure the first chapter is active from start
                    setTimeout(() => {
                        if (app.chapters.length) {
                            app.chapters.forEach((item) => {
                                item.active = false;
                            });
                            app.chapters[0].active = true;
                        }
                    }, 50);


                    app.appReady = true;

                },
                randStr(length) {
                    let result = '';
                    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
                    const charactersLength = characters.length;
                    let counter = 0;
                    while (counter < length) {
                        result += characters.charAt(Math.floor(Math.random() * charactersLength));
                        counter += 1;
                    }
                    return result;
                },
                scrollToChapter(chapter, contentClick = false) {
                    let app = this;

                    // Close narrow view if open
                    this.closeNarrowView();


                    this.$nextTick(() => {
                        // If initiated from content (anchor links) look for the chapter in the list
                        if (contentClick) {
                            chapter = app.chapters.find((item) => {
                                return item.url == chapter.url;
                            });
                        }


                        let element = document.querySelector(chapter.url);

                        this.doingScroll = true;

                        // Since waypoint is ignored at thios point, we need to manually set the active chapter
                        app.chapters.forEach((item) => {
                            item.active = false;
                        });
                        chapter.active = true;


                        if (element) {
                            element.scrollIntoView({
                                behavior: 'smooth'
                            });

                            setTimeout(() => {
                                this.doingScroll = false;

                                if (contentClick) {
                                    // Add hash to url
                                    window.location.hash = chapter.url;
                                }
                            }, 500);
                        }
                    });


                },
                openNarrowView() {
                    let app = this;
                    this.narrow.open = true;
                    // Get current scroll pos of body
                    this.narrow.scrollPos = window.scrollY;
                    document.body.classList.add('narrow-menu-open');

                    this.$nextTick(() => {
                        document.body.scrollTop = app.narrow.scrollPos;
                    });
                },
                closeNarrowView() {
                    let app = this;
                    this.narrow.open = false;
                    document.body.classList.remove('narrow-menu-open');

                    this.$nextTick(() => {
                        window.scrollTo({
                            top: app.narrow.scrollPos,
                        });
                    });
                },
                scrollToTop() {
                    window.scrollTo({
                        top: 0,
                        behavior: 'smooth'
                    });
                },

            },
            mounted: function () {
                if(!this.settings){
                    console.log('NO SETTINGS');
                    return;
                }

                this.init();
            },
            created() {
            },
            components: {},
        });


        // Mount app to DOM
        if (document.getElementById("webien-toc-widget-" + el.dataset.unique)) {
            $app.mount('#webien-toc-widget-' + el.dataset.unique);
        }


    });
}

