class PageLayerModel {
    constructor() {
        this.status = {};
        this.events = new EventNode(); 
    } 
    async loadPage(url) {
		this.dispatchPageLoadStateChange('loading');
		try {
			const response = await fetch(url, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
					'X-Requested-With': 'XMLHttpRequest'
				}
			});

			const data = await response.text();
			const parser = new DOMParser();
			const doc = parser.parseFromString(data, 'text/html');
			const mainElement = doc.querySelector('main');

			if (mainElement) {
				const specificContent = mainElement.innerHTML;
				this.events.dispatchEvent(new CustomEvent('pageLoaded', { detail: specificContent }));
				this.dispatchPageLoadStateChange('loaded');
			} else {
				throw new Error('Main content not found');
			}
		} catch (error) {
			console.error('Error:', error);
			this.dispatchPageLoadStateChange('error');
		}
	}
 
    dispatchPageLoadStateChange(state) {
        this.events.dispatchEvent(new CustomEvent('pageLoadStateChange', { detail: state }));
    }
} 

class PageLayer {
    constructor($id, $par, $url, $exists) {
        this.id = "pagelayer-" + this.getRandomID();
        this.par = $par;
        this.url = $url;
        this.events = new EventNode();
        this.viewportWidth = Utilities.get_viewport_width();
        this.viewportHeight = Utilities.get_viewport_height();
        this.transitionType = Utilities.getTransitionType();
        this.animationType = Utilities.getAnimationType();
        this.page = this.createPageLayerElement();
        this.defaults = {};
        this.animating = false;
        this.exists = $exists;
        this.direction = "right";

        this.handleNextButtonClick = this.handleButtonClick.bind( this, ".pagination-item.right", "nextPageClick" );
        this.handlePrevButtonClick = this.handleButtonClick.bind( this, ".pagination-item.left", "previousPageClick" );

        //throttle keys so the browser doesn't choke if keys held down
        this.handleKeydown = Utilities.throttle(this.handleKeydown.bind(this), 1000);
        document.addEventListener("keydown", this.handleKeydown);

        if (!this.exists) {
            this.loadPage($url);
        } else {
            this.wrapPage();
        }
    }

    wrapPage() {
        const main = document.querySelector(".pageinner");
        if (main) { 
            main.parentNode.insertBefore(this.page, main);
            this.page.appendChild(main);
            this.page.classList.add( "active", "page-ontop", "pageimmediateupdate" );
            this.events.dispatchEvent(new CustomEvent("showingPage", {}));
            this.addCloseButton();
            this.enablePreviousNext();
            this.imgsLoaded(main);
        }
    }

    createPageLayerElement() {
        if (this.animating) return;
        const parentElement = document.querySelector(this.par);
        if (!parentElement) {
            console.error("Parent element not found for selector:", this.par);
            return null;
        }
        const pagelayer = document.createElement("div");
        pagelayer.id = this.id;
        pagelayer.classList.add("pagelayer");
        parentElement.appendChild(pagelayer);
        return pagelayer;
    }

    loadPage($url) {
        if (this.animating) return;
        const $pageLayerModel = new PageLayerModel();
        $pageLayerModel.events.addEventListener(
            "pageLoaded",
            (e) => {
                this.show(e.detail);
                this.events.dispatchEvent(
                    new CustomEvent("pageLoaded", { detail: e.detail })
                );
            },
            false
        );
        $pageLayerModel.loadPage($url);
    }

    show($data) {
        if (this.animating) return;

        // Clear existing content
        this.page.innerHTML = "";

        // Safely insert HTML content
        this.page.insertAdjacentHTML("beforeend", $data);

        // Apply necessary class changes and dispatch events
        const classList = this.page.classList;
        classList.remove("pagemoveToRight", "pagemoveToLeft");
        const $directionclass =
            this.direction === "right" ? "pagemoveToLeft" : "pagemoveToRight";
        classList.add("animating", "active", "page-ontop", $directionclass);
        this.events.dispatchEvent(new CustomEvent("showingPage", {}));
        this.addCloseButton();
        this.enablePreviousNext();
        adjustIframes();
        wrapVideoIframes(); 
    }

    hide() {
        if (this.animating) return;
        const classList = this.page.classList;
        classList.add("pagemoveToRight", "hiding");
        this.animating = true;
        this.events.dispatchEvent(new CustomEvent("pageHidden", {}));
        this.page.addEventListener("animationend", this.handleAnimationEnd);
    }

    handleAnimationEnd = (event) => {
        if (
            event.target === this.page &&
            this.page.classList.contains("hiding")
        ) {
            this.remove();
            this.animating = false;
        }
    };

    remove() {
        if (!this.page) return;
        this.page.remove();
        this.events.dispatchEvent(new CustomEvent("pageRemoved", {}));
        this.page.removeEventListener("animationend", this.handleAnimationEnd);
    }

    addCloseButton() {
        const closeButton = document.createElement("div");
        closeButton.className = "overlay-close";
        closeButton.innerHTML = "<span></span><span></span>";
        this.page.appendChild(closeButton);
        const swipe = new Swipe(this.page);
        swipe.onRight(() => {
            document.body.classList.remove("no-scroll");
            this.hide();
            swipe.kill();
        });
        swipe.run(); 
        closeButton.addEventListener( "click", () => { this.hide(); }, false );
        document.addEventListener("keydown", (e) => {
            if (e.key === "Escape") { this.hide(); }
        });
    }

    handleButtonClick(selector, eventName, e) {
        e.preventDefault();
        const targetButton = e.target.closest(selector);
        this.direction = selector.includes("left") ? "left" : "right";
        this.events.dispatchEvent(
            new CustomEvent(eventName, { detail: targetButton.href })
        );
    }

    handleKeydown(e) {
        const nextButton = this.page.querySelector(".pagination-item.right");
        const previousButton = this.page.querySelector(".pagination-item.left");
        const closeButton = this.page.querySelector(".overlay-close");

        switch (e.key) {
            case "ArrowRight":
                if (nextButton) nextButton.click();
                break;
            case "ArrowLeft":
                if (previousButton) previousButton.click();
                break;
            case "Escape":
                if (closeButton) closeButton.click();
                break;
        }
    }

    enablePreviousNext() {
        // Remove existing listeners
        const prevButton = this.page.querySelector(".pagination-item.left");
        if (prevButton) {
            prevButton.removeEventListener("click", this.handlePrevButtonClick);
            prevButton.addEventListener("click", this.handlePrevButtonClick);
        }

        const nextButton = this.page.querySelector(".pagination-item.right");
        if (nextButton) {
            nextButton.removeEventListener("click", this.handleNextButtonClick);
            nextButton.addEventListener("click", this.handleNextButtonClick);
        }

        // Attach keydown event listener

        document.removeEventListener("keydown", this.handleKeydown);
        document.addEventListener("keydown", this.handleKeydown);
    }

    getRandomID() {
        return Math.random()
            .toString(36)
            .replace(/[^a-z]+/g, "");
    }
}
const nonce = "<?= option('nonce'); ?>"; 

class BLURSTUDIO {
    constructor() {
        this.defaults = {};
        this.active_page = false;
        this.previous_page = false;
        this.layers = [];
        this.events = new EventNode();
    }

    init(options) {
        this.viewportWidth = Utilities.get_viewport_width();
        this.viewportHeight = Utilities.get_viewport_height();
        this.transitionType = Utilities.getTransitionType();
        this.animationType = Utilities.getAnimationType();

        this.anilib = new AniLib({
            animateClass: "animated",
            offset: 50,
        });

        this.anilib.init();
        this.enableProject();
        this.enableFeed();

        // load hash url from feed if it exists
        if (document.querySelector(".feed-tpl")) {
            if (window.location.hash) {
                var preloadurl = String(window.location);
                preloadurl = preloadurl.replace("#", "");
                this.changePage("Layer", preloadurl, false);
            }
        }

        window.addEventListener(
            "resize",
            Utilities.debounce(this.displayResized, 150).bind(this)
        );
        window.addEventListener("popstate", this.popstatehandler.bind(this));

        if (
            document.querySelector(".home-tpl") ||
            document.querySelector(".projects-tpl")
        ) {
            this.initLoader();
        }
    }

    initLoader() {
        document.body.classList.add("no-scroll");
        document.addEventListener("DOMContentLoaded", () => {
            this.handleDomContentLoaded();
        });
        window.addEventListener("load", () => {
            this.handleWindowLoad();
        });
    }

    handleDomContentLoaded() {
        document.body.classList.remove("no-scroll");
    }

    handleWindowLoad() {
        this.showIntroTransition();
    }

    loaderComplete() {
        document.querySelector("#loader-screen").classList.add("hidden");
        document.body.classList.remove("no-scroll");
    }

    showIntroTransition() {
        setTimeout(() => {
            document.querySelector(".load-panel-1").classList.add("reveal");
        }, 1000);
        setTimeout(() => {
            this.loaderComplete();
        }, 2000);
    }

    showOutroTransition(href) {
        document.querySelector("#loader-screen").classList.remove("hidden");
        try {
            document.querySelector(".load-panel-3").classList.add("reveal");
            setTimeout(() => {
                location.href = href;
            }, 2000);
        } catch (error) {}
    }

    enableProject() {
        const playButtons = document.querySelectorAll(".canplay");
        const $this = this;
        if (playButtons.length === 0) return;
        playButtons.forEach((button) => {
            if (button.hasAttribute("data-video")) {
                button.addEventListener("click", function (e) {
                    e.preventDefault();
                    const vidId = this.getAttribute("data-video");
                    $this.loadVideo(vidId, this.querySelector(".table-cell"));
                });
            }
        });
    }

    noscroll(e) {
        e.stopPropagation();
        e.preventDefault();
        e.returnValue = false;
        return false;
    }

    disableScrolling() {
        document.removeEventListener("DOMMouseScroll", this.elementScroll);
        document.removeEventListener("wheel", this.elementScroll);
        document.removeEventListener("wheel", this.elementScroll);
        window.addEventListener("scroll", this.noscroll);
    }

    enableScrolling() {
        document.addEventListener("DOMMouseScroll", this.elementScroll);
        document.addEventListener("wheel", this.elementScroll);
        document.addEventListener("wheel", this.elementScroll);
        window.removeEventListener("scroll", this.noscroll);
    }

    showPanel() {
        this.delta = 0;
        this.slides.forEach(function (slide, index) {
            this.slide.toggleClass("active", i >= this.currentSlideIndex);
        });
    }

    enableFeed() {
        const listitems = document.querySelectorAll(".feed-entry");
        for (var i = 0; i < listitems.length; i++) {
            const tmpitem = listitems[i];
            const $this = this;

            tmpitem.addEventListener("click", function (e) {
                e.preventDefault();
                if (this.classList.contains("projects-menu-item")) return;
                const $url = this.querySelector("a");
                const $id = "Layer";
                if (this.hasAttribute("data-id")) {
                    $id = "layer-" + this.getAttribute("data-id");
                }

                $this.changePage($id, $url, false);
            });
        }
    }

    enablePrimaryNav() {
        const ident = document.querySelector("#identity");
        const navpanel = document.querySelector("#nav-panel");

        ident.addEventListener("mouseover", function (e) {
            navpanel.classList.add("blur");
        });
        ident.addEventListener("mouseout", function (e) {
            navpanel.classList.remove("blur");
        });

        const listitems = document.querySelectorAll(".menu li");
        const $this = this;

        for (var i = 0; i < listitems.length; i++) {
            const tmpitem = listitems[i];
            tmpitem.addEventListener("mouseover", function (e) {
                if (
                    this.hasAttribute("data-bgclr") &&
                    this.getAttribute("data-bgclr") != ""
                ) {
                    const bgclr = this.getAttribute("data-bgclr");
                    document.body.style.backgroundColor = bgclr || "#000000";
                }
            });

            tmpitem.addEventListener("mouseout", function (e) {
                document.body.style.backgroundColor = "";
            });

            tmpitem.addEventListener("click", function (e) {
                e.preventDefault();
                if (this.classList.contains("projects-menu-item")) return;
                const $url = this.querySelector("a");
                let $id = "Layer";
                if (this.hasAttribute("data-id")) {
                    $id = "layer-" + this.getAttribute("data-id");
                }
                $this.changePage($id, $url, false);
            });
        }
    }

    safelyModifyDOM(selector, action, className) {
        const element = document.querySelector(selector);
        if (element) {
            element.classList[action](className);
        }
    }

    removePage(url) {
        const index = this.layers.indexOf(url);
        if (index > -1) {
            this.layers.splice(index, 1);
        }
    }

    handlePageHidden() {
        const identityLink = document.querySelector("#identity a");
        if (identityLink) {
            this.formatPageTitle(identityLink.textContent);
        }
        this.safelyModifyDOM("#mast", "add", "page-ontop");
        this.safelyModifyDOM("body", "remove", "no-scroll");
    }

    handlePageRemoved($url) {
        this.safelyModifyDOM("#mast", "add", "page-ontop");

        const basePath = window.location.pathname.split("/")[1];  
        const newPath = `https://blur.com/feed/`;
        window.history.pushState(document.title, document.title, newPath);

        this.safelyModifyDOM("body", "remove", "no-scroll");
        this.removePage($url);
    }

    handlePageLoaded($pagelayer, $url) {
        const h1 = $pagelayer.page.querySelector("h1");
        if (h1) {
            this.formatPageTitle(h1.textContent);
        }

        window.history.pushState(document.title, document.title, $url);
    }
    handleAnimationComplete() {
        this.safelyModifyDOM("body", "remove", "no-scroll");
        this.resizePages();
    }

    handleNextPreviousPageClick($id, detail) {
        this.nextPrevPage($id, detail);
    }

    handleImagesLoaded() {
        this.displayResized({});
    }

    changePage($id, $url, $exists) {
        if (this.previous_page) {
            this.previous_page.hide();
        }

        const $pagelayer = new PageLayer($id, "body", $url, $exists);
        this.active_page = $pagelayer;

        if (!this.layers.includes($url)) {
            this.layers.push($url);
        }
        if (!$exists) {
            document.body.classList.add("no-scroll");
        }

        this.addEventListenersToPageLayer($pagelayer, $url, $id);
        this.previous_page = this.active_page;
        this.resizePages();

        setTimeout(() => this.resizePages(), 1000);
    }

    addEventListenersToPageLayer($pagelayer, $url, $id) {
        $pagelayer.events.addEventListener(
            "pageHidden",
            this.handlePageHidden.bind(this),
            false
        );
        $pagelayer.events.addEventListener(
            "pageRemoved",
            () => this.handlePageRemoved($url),
            false
        );
        $pagelayer.events.addEventListener(
            "pageLoaded",
            () => this.handlePageLoaded($pagelayer, $url),
            false
        );
        $pagelayer.events.addEventListener(
            "animationComplete",
            this.handleAnimationComplete.bind(this),
            false
        );
        $pagelayer.events.addEventListener(
            "nextPageClick",
            (e) => this.handleNextPreviousPageClick($id, e.detail),
            false
        );
        $pagelayer.events.addEventListener(
            "previousPageClick",
            (e) => this.handleNextPreviousPageClick($id, e.detail),
            false
        );
        $pagelayer.events.addEventListener(
            "imagesLoaded",
            this.handleImagesLoaded.bind(this),
            false
        );
    }

    nextPrevPage($id, $cont) {
        document.body.classList.remove("no-scroll");
        if ($cont == null) return;
        this.changePage($id, $cont);
    }

    popstatehandler(event) {
        try {
            if (event.state && event.state.title) {
                this.changePage("back", event.state.url);
            } else if (this.active_page) {
                this.active_page.hide();
            }
        } catch (error) {
            console.error("Error handling popstate:", error);
        }
    }

    formatPageTitle(pageTitle) {
        const baseTitle = document.querySelector("#identity a").textContent;
        const formattedTitle =
            pageTitle !== baseTitle ? `${baseTitle} | ${pageTitle}` : baseTitle;
        document.title = formattedTitle;
    }

    resizePages() {
        this.documentheight = Utilities.get_document_height();
        this.viewportWidth = Utilities.get_viewport_width();
        this.viewportHeight = Utilities.get_viewport_height();

        const mastHeight = document.querySelector("#mast").offsetHeight || 0;
        const identityHeight =
            document.querySelector("#identity").offsetHeight || 0;
        const coreHeight = identityHeight + mastHeight;

        let pageHeight;
        if (
            this.active_page &&
            this.active_page.page.classList.contains("active")
        ) {
            const pagelayerHeight = this.active_page.page.offsetHeight || 0;
            pageHeight = Math.max(pagelayerHeight, this.viewportHeight);
        } else {
            pageHeight = coreHeight;
            document.body.style.height = null;
        }
        if (
            this.active_page &&
            this.active_page.page.querySelector(".pageinner")
        ) {
            const pageInner = this.active_page.page.querySelector(".pageinner");
            pageInner.style.height = `${pageHeight}px`;
        }
    }

    moveToTop() {
        window.scroll({ top: 0, left: 0, behavior: "instant" });
    }
    displayResized(e) {
        this.resizePages();
    }

    loadVideo(id, location, w, h) {
        let contentHtml = "";

        if (isNaN(id)) {
            if (id.endsWith(".mp4")) {
                // MP4
                contentHtml = `
                    <video controls="true" autoplay class="video">
                        <source src="${id}"  nonce="${nonce}"  type="video/mp4" id="home-mp4-src">
                    </video>`;
            } else {
                // YouTube
                contentHtml = `
                    <div class="inner anilib fadeIn" style="margin-top:50px">
                        <div style="padding:56.25% 0 0 0; position:relative;">
                            <iframe  nonce="${nonce}"  frameborder="0" scrolling="no" marginheight="0" marginwidth="0" style="position:absolute; top:0; left:0; width:100%; height:100%;" type="text/html" src="https://www.youtube.com/embed/${id}?autoplay=1&fs=1&iv_load_policy=3&showinfo=0&rel=0&cc_load_policy=0&start=0&end=0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
                        </div>
                    </div>`;
            }
        } else {
            // Vimeo/default
            contentHtml = `
                <div class="inner anilib fadeIn">
                    <div style="padding:56.25% 0 0 0; position:relative;">
                        <iframe src="https://player.vimeo.com/video/${id}?autoplay=1&title=0&byline=0&portrait=0" nonce="${nonce}" style="position:absolute; top:0; left:0; width:100%; height:100%;" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
                    </div>
                </div>`;
        }

        overlayContent.show(contentHtml);
    }
}
 
 
Array.from(
    document.querySelectorAll(
        ".content-sections img, .note-text img, .feed-article header img, .feed-article .note-text img"
    )
).forEach((element) => {
    element.onclick = (e) => {
        e.preventDefault();
        basicLightbox.create(`<img src="${element.src}">`).show();
    };
});

function adjustIframes() {
    const iframes = document.querySelectorAll("iframe");
    iframes.forEach((iframe) => {
        iframe.removeAttribute("width");
        iframe.removeAttribute("height");
    });
}
function wrapVideoIframes() {
    const iframes = document.querySelectorAll("iframe");
    iframes.forEach((iframe) => {
        const parent = iframe.parentNode;
        const isAlreadyWrapped =
            (parent.tagName === "DIV" || parent.tagName === "FIGURE") &&
            parent.classList.contains("video");

        if (!isAlreadyWrapped) {
            const wrapper = document.createElement("div");
            wrapper.className = "video";
            parent.insertBefore(wrapper, iframe);
            wrapper.appendChild(iframe);
        }
    });
}


const $Utilities = new Utilities();
const $BLURSTUDIO = new BLURSTUDIO();
$BLURSTUDIO.init(); 

adjustIframes();
wrapVideoIframes(); 
