/**
 * Creates a visual progress bar for the presentation.
 */
export default class Progress {
    constructor(Reveal) {
        this.Reveal = Reveal;

        this.onProgressClicked = this.onProgressClicked.bind(this);
    }

    render() {
        this.element = document.createElement("div");
        this.element.className = "progress";
        this.Reveal.getRevealElement().appendChild(this.element);

        this.bar = document.createElement("span");
        this.element.appendChild(this.bar);
    }

    /**
     * Called when the reveal.js config is updated.
     */
    configure(config, oldConfig) {
        this.element.style.display = config.progress ? "block" : "none";
    }

    bind() {
        if (this.Reveal.getConfig().progress && this.element) {
            this.element.addEventListener(
                "click",
                this.onProgressClicked,
                false,
            );
        }
    }

    unbind() {
        if (this.Reveal.getConfig().progress && this.element) {
            this.element.removeEventListener(
                "click",
                this.onProgressClicked,
                false,
            );
        }
    }

    /**
     * Updates the progress bar to reflect the current slide.
     */
    update() {
        // Update progress if enabled
        if (this.Reveal.getConfig().progress && this.bar) {
            let scale = this.Reveal.getProgress();

            // Don't fill the progress bar if there's only one slide
            if (this.Reveal.getTotalSlides() < 2) {
                scale = 0;
            }

            this.bar.style.transform = "scaleX(" + scale + ")";
        }
    }

    getMaxWidth() {
        return this.Reveal.getRevealElement().offsetWidth;
    }

    /**
     * Clicking on the progress bar results in a navigation to the
     * closest approximate horizontal slide using this equation:
     *
     * ( clickX / presentationWidth ) * numberOfSlides
     *
     * @param {object} event
     */
    onProgressClicked(event) {
        this.Reveal.onUserInput(event);

        event.preventDefault();

        let slides = this.Reveal.getSlides();
        let slidesTotal = slides.length;
        let slideIndex = Math.floor(
            (event.clientX / this.getMaxWidth()) * slidesTotal,
        );

        if (this.Reveal.getConfig().rtl) {
            slideIndex = slidesTotal - slideIndex;
        }

        let targetIndices = this.Reveal.getIndices(slides[slideIndex]);
        this.Reveal.slide(targetIndices.h, targetIndices.v);
    }

    destroy() {
        this.element.remove();
    }
}
