/**
 * @typedef {Object} Page 
 * @property {HTMLElement} element
 * @property {(...args: any[]) => void} init
 * @property {boolean} always_mode 
 * @property {boolean} [first_init]
 */

/**
 * @param {string | HTMLElement} element  
 * @returns {HTMLElement}
*/
const get_element = recovery((element) => {
    if(element instanceof HTMLElement)
        return element
    else if(typeof element === 'string')
        return document.getElementById(element)
    else 
        throw new Error(`element is not correct: ${element}`)
})

/**
 * @class PageManager
 * @property {Object<string, Page>} pages 
 * @property {HTMLElement} page_space
 */
class PageManager {

    /**
     * @param {string | HTMLElement} page_space_id 
     * @param  {...Page} args 
     */
    constructor(page_space_id, ...args) {
        recovery((page_space_id_f, ...args_f) => {
            this.pages = {}
            this.page_space = get_element(page_space_id_f)
            let first_id

            args_f.forEach((arg, index) => {
                const {element, init = () => {}, always_mode = false} = arg
                const el = get_element(element)
                if(el instanceof HTMLElement){
                    const id = el.id?.trim() || `_page_${index}`
                    this.pages[id] = {element: el, init, always_mode}
                    if(first_id == null) first_id = id
                } else
                    logger.wprint(`${element} is not html-element or id`)
            })
        }, logger.eprint) (page_space_id, ...args)
    }

    /**
     * @param {string} page_id
     * @param {...*} args
     */
    set_page = recovery((page_id, ...args) => {
        const page = this.pages[page_id]

        this.page_space.innerHTML = ''
        this.page_space.appendChild(page.element)

        if(!page.first_init || page.always_mode) {
            page.init(...args)
            if(!page.first_init) page.first_init = true
        }
    }, logger.eprint)
}