/**
 * Wrapper object for USWDS accordions.
 */
class FSAccordion {

    //#region Inner Members
    #id;
    #button;
    #content;

    //#endregion

    //#region Construction and Initialization
    constructor(id) {
        this.#id = id;
    }
    
    #initButon() {
        let selector = `[aria-controls="${this.#id}"]`;
        this.#button = document.querySelector(selector);
    }

    #initContent() {
        this.#content = document.getElementById(this.#id);
    }

    //#endregion

    //#region Properties

    /**
     * Returns the button that controls the accordion and contains its header.
     */
    get button() {
        if (this.#button == null) {
            this.#initButon();
        }
        return this.#button;
    }

    /**
     * Returns the div containing the accordion content.
     */
    get content() {
        if (this.#content == null) {
            this.#initContent();
        }
        return this.#content;
    }

    /**
     * The element id in the aria-controls attribute of the accordion.
     */
    get id() {
        return this.#id;
    }
    set id(value) 
    {
        this.#id = value;
    }

    //#endregion

    //#region Methods

    /**
     * Collapses the accordion.
     */
    collapse() {
        this.button.setAttribute('aria-expanded', "false");
        this.content.hidden = true;
    }

    /**
     * Expands the accordion and scrolls the view port to the accordion.
     */
    goto(scrollToSelector = null) {
        this.expand();
        let scrollTarget = this.button;
        if (scrollToSelector != null) {
            scrollTarget = this.content.querySelector(scrollToSelector);
        }
        scrollTarget.scrollIntoView();
    }

    /**
     * Expands the accordion.
     */
    expand() {
        this.button.setAttribute('aria-expanded', "true");
        this.content.hidden = false;
    }

    //#endregion

}

/**
 * A collection of FSAccordion objects.
 */
class FSAccordions {

    //#region Inner Members
    
    #accordions = new Map();
    #containerSelector;
    #controlsPanel;
    #collapseAllButton;
    #expandAllButton;
    #intersectionObserver;

    //#endregion

    //#region Event Handlers

    collapseAllClick = (event) => {
        this.collapseAll();
    }

    collapseAllMouseEnter = (event) => {
        this.#collapseAllButton.innerText = "Collapse All";
    }

    collapseAllMouseLeave = (event) => {
        this.#collapseAllButton.innerText = "-";
    }

    expandAllClick = (event) => {
        this.expandAll();
    }

    expandAllMouseEnter = (event) => {
        this.#expandAllButton.innerText = "Expand All";
    }

    expandAllMouseLeave = (event) => {
        this.#expandAllButton.innerText = "+";
    }

    intersectionObserverCallback = (entries) => {
        entries.forEach((entry) => {
            if (entry.isIntersecting) {
                this.#controlsPanel.hidden = false;
            } else {
                this.#controlsPanel.hidden = true;
            }
        });
    }

    //#endregion

    //#region Construction and Initialization
    constructor(containerSelector = null) {
        if (containerSelector != null) {
            this.#containerSelector = containerSelector;
            if (this.container != null) {
                this.#init();
            }
        }
    }

    #init() {
        this.#initContent();
        this.#initControls();
        this.#initIntersectionObserver();
    }

    #initContent() {
                let contentDivs = this.container.querySelectorAll(".usa-accordion__content");
        contentDivs.forEach(contentDiv => {
            let id = contentDiv.getAttribute('id');
            let accordion = new FSAccordion(id);
            this.#accordions.set(id, accordion);
        });
    }

    #initExpandAllButton() {
        this.#expandAllButton = document.createElement("a");
        this.#expandAllButton.setAttribute('class', 'usa-button');
        this.#expandAllButton.innerText = "+";
        this.#expandAllButton.href = "javascript:void(0);";
        this.#expandAllButton.addEventListener("mouseenter", this.expandAllMouseEnter);
        this.#expandAllButton.addEventListener("mouseleave", this.expandAllMouseLeave);
        this.#expandAllButton.addEventListener("focus", this.expandAllMouseEnter);
        this.#expandAllButton.addEventListener("blur", this.expandAllMouseLeave);
        this.#expandAllButton.addEventListener("click", this.expandAllClick);
        this.#controlsPanel.appendChild(this.#expandAllButton);
    }

    #initCollapseAllButton() {
        this.#collapseAllButton = document.createElement("a");
        this.#collapseAllButton.setAttribute('class', 'usa-button');
        this.#collapseAllButton.innerText = "-";
        this.#collapseAllButton.href = "javascript:void(0);";
        this.#collapseAllButton.addEventListener("mouseenter", this.collapseAllMouseEnter);
        this.#collapseAllButton.addEventListener("mouseleave", this.collapseAllMouseLeave);
        this.#collapseAllButton.addEventListener("focus", this.collapseAllMouseEnter);
        this.#collapseAllButton.addEventListener("blur", this.collapseAllMouseLeave);
        this.#collapseAllButton.addEventListener("click", this.collapseAllClick);
        this.#controlsPanel.appendChild(this.#collapseAllButton);
    }

    #initControls() {
        this.#controlsPanel = document.createElement("div");
        this.#controlsPanel.setAttribute('class', "fs-accordions-controls");
        this.#controlsPanel.style = "z-index: 2000; position: fixed; right:0; bottom:1rem;";
        this.#controlsPanel.hidden = true;
        this.#initCollapseAllButton();
        this.#initExpandAllButton();
        this.container.appendChild(this.#controlsPanel);
    }

    #initIntersectionObserver() {
        this.#intersectionObserver = new IntersectionObserver(this.intersectionObserverCallback);
        this.#intersectionObserver.observe(this.container);
    }

    //#endregion

    //#region Properties

    /**
     * Gets the element that matches containerSelector.
     */
    get container() {
        return document.querySelector(this.#containerSelector);
    }

    /**
     * The selector used to find the container to search for accordions. 
     */
    get containerSelector() {
        return this.#containerSelector;
    }
    set containerSelector(value) {
        this.#containerSelector = value;
    }

    //#endregion

    //#region Methods

    collapseAll() {
        this.#accordions.forEach(accordion => {
            accordion.collapse();
        });
    }

    expandAll() {
        this.#accordions.forEach(accordion => {
            accordion.expand();
        });
    }

    goto(id, scrollToSelector = null) {
        this.#accordions.get(id).goto(scrollToSelector);
    }

    //#endregion
}


/**
 * Initialize the list object
 */
let fsAccordions = new FSAccordions(".fs-accordion-container");