<template>
    <teleport to="#content">
        <div id="navmap">
            <nav>
                <a class="top" href="#top">
                    <i class="fa fa-fw fa-square" />
                    <span>{{ $t("nav.top") }}</span>
                </a>
                <item
                    v-for="item of items"
                    :key="item.key"
                    :item="item"
                    :step="step"
                />
            </nav>
        </div>
    </teleport>
</template>

<script>
import Item from "./StickyNav/Item.vue";

export default {
    name: "StickyNav",
    components: {
        Item,
    },
    data() {
        return {
            header: document.querySelector("header nav.navbar"),
            bannerName: document.querySelector(
                "#header-accompanying_course-name",
            ),
            bannerDetails: document.querySelector(
                "#header-accompanying_course-details",
            ),
            container: null,
            heightSum: null,
            stickyNav: null,
            limit: 25,
            anchors: null,
            items: [],
        };
    },
    computed: {
        accompanyingCourse() {
            return this.$store.state.accompanyingCourse;
        },
        step() {
            return this.accompanyingCourse.step;
        },
        top() {
            return parseInt(
                window
                    .getComputedStyle(this.stickyNav)
                    .getPropertyValue("top")
                    .slice(0, -2),
            );
        },
    },
    mounted() {
        this.ready();
        window.addEventListener("scroll", this.handleScroll);
    },
    unmounted() {
        window.removeEventListener("scroll", this.handleScroll);
    },
    methods: {
        ready() {
            // load datas DOM when mounted ready
            this.container = document.querySelector("#content");
            this.stickyNav = document.querySelector("#navmap");
            this.anchors = document.querySelectorAll("h2 a[id^='section']");
            this.initItemsMap();

            // TODO resizeObserver not supports IE !
            // Listen when elements change size, then recalculate heightSum and initItemsMap
            const resizeObserver = new ResizeObserver(() => {
                this.refreshPos();
            });

            resizeObserver.observe(this.header);
            resizeObserver.observe(this.bannerName);
            resizeObserver.observe(this.bannerDetails);
            resizeObserver.observe(this.container);
        },
        initItemsMap() {
            this.anchors.forEach((anchor) => {
                this.items.push({
                    pos: null,
                    active: false,
                    key: parseInt(anchor.id.slice(8).slice(0, -1)),
                    id: "#" + anchor.id,
                });
            });
        },
        refreshPos() {
            //console.log('refreshPos');
            this.heightSum =
                this.header.offsetHeight +
                this.bannerName.offsetHeight +
                this.bannerDetails.offsetHeight;

            this.anchors.forEach((anchor, i) => {
                this.items[i].pos = this.findPos(anchor)["y"];
            });
        },
        findPos(element) {
            let posX = 0,
                posY = 0;
            do {
                posX += element.offsetLeft;
                posY += element.offsetTop;
                element = element.offsetParent;
            } while (element != null);

            let pos = [];
            pos["x"] = posX;
            pos["y"] = posY;

            return pos;
        },
        handleScroll() {
            let pos = this.findPos(this.stickyNav);
            let top = this.heightSum + this.top - window.scrollY;
            //console.log(window.scrollY);

            if (top > this.limit) {
                this.stickyNav.style.position = "absolute";
                this.stickyNav.style.left = "10px";
            } else {
                this.stickyNav.style.position = "fixed";
                this.stickyNav.style.left = pos["x"] + "px";
            }

            this.switchActive();
        },
        switchActive() {
            this.items.forEach((item, i) => {
                let next = this.items[i + 1] ? this.items[i + 1].pos : "100000";
                item.active =
                    (window.scrollY >= item.pos) & (window.scrollY < next)
                        ? true
                        : false;
            }, this);

            // last item never switch active because scroll reach bottom of page
            if (
                document.body.scrollHeight ==
                window.scrollY + window.innerHeight
            ) {
                this.items[this.items.length - 1].active = true;
                this.items[this.items.length - 2].active = false;
            } else {
                this.items[this.items.length - 1].active = false;
            }
        },
    },
};
</script>

<style lang="scss">
div#content {
    position: relative;

    div#navmap {
        position: absolute;
        top: 30px;
        left: 10px; //-10%;
        nav {
            font-size: small;
            a {
                display: block;
                box-sizing: border-box;
                margin-bottom: -3px;
                color: #71859669;
                text-decoration: none;
                &.top {
                    color: #718596;
                }
                span {
                    display: none;
                }
                &:hover,
                &.active {
                    span {
                        display: inline;
                        padding-left: 8px;
                    }
                }
                &:hover {
                    color: #718596b5;
                }
                &.active {
                    color: #e2793d; //orange
                    //color: #eec84a; //jaune
                }
            }
        }
    }
}
@media only screen and (max-width: 768px) {
    div#navmap {
        display: none;
    }
}
</style>
