// <<hpp_insert gen/Window.js>>

/**
 * Display a modal window with helpful information.
 * @typedef DiagramHelp
 */
class DiagramHelp extends Window {
    /**
     * Using data generated by Toolbar, document each of the buttons.
     * @param {Object} helpInfo Data structure containing Toolbar button info.
     */
    constructor(helpInfo, footerText = '') {
        super();

        this.theme('help')
            .setList({ left: '100px', top: '20px', right: '100px', height: '850px' })
            .title('Instructions')
            .footerText(footerText);

        this.absorbBody('#toolbar-help-container');

        this.helpDiv = this.body.select('div.help-graphic');
        this.helpSvg = this.helpDiv.select('#help-graphic-svg');

        this._addButtonHelpText(helpInfo);

        this.show().modal(true);
    }

    /** Override Window::close() to just hide the help window. */
    close() {
        this.modal(false);
        this.hide();
        return this;
    }

    /**
     * Add a line of text for each button. Buttons not contained in an expandable
     * menu are labeled to the left, while the expansion buttons are described
     * in groups at the right.
     * @param {Object} helpInfo Data structure containing Toolbar button info.
     */
    _addButtonHelpText(helpInfo) {
        let topPx = 20;
        for (const btnId in helpInfo.buttons) {
            const btn = helpInfo.buttons[btnId];

            // Detail the "primary" toolbar buttons
            if (!btn.expansionItem) {
                const btnText = this.helpDiv.append('p').attr('class', 'help-text');
                btn.helpWinText = btnText;
                btnText.style('left', helpInfo.width + 5 + 'px')
                    .style('top', btn.bbox.top + btn.bbox.height / 2 - 13 + 'px')
                    .text(btn.desc);

                // Detail the expansion buttons
                let grp = null;
                if (btnId in helpInfo.primaryButtons) {
                    btnText.classed('help-button-group', true)
                    grp = this.helpDiv.append('div')
                        .attr('id', btnId + '-help-group')
                        .attr('class', 'help-button-group')
                        .style('top', topPx + 'px')

                    for (const memId of helpInfo.primaryButtons[btnId]) {
                        const memClasses = d3.select('#' + memId).attr('class').split(/ /);

                        let memClass = '';
                        for (const mc of memClasses) {
                            if (mc.match(/^icon-/)) {
                                memClass = mc;
                                break;
                            }
                        }
                        grp.append('p').attr('class', 'help-text')
                            .html(`<i class="fas ${memClass} help-text-icon"></i><span>${helpInfo.buttons[memId].desc}</span>`)
                    }

                    const grpBbox = grp.node().getBoundingClientRect();
                    topPx += grpBbox.height + 25;

                    this._drawGroupLines(btnText, grp)
                }
            }
        }
    }

    /**
     * Draw a path in SVG connecting the button that opens the expansion
     * to the boxes containing descriptions of the individual buttons.
     */
    _drawGroupLines(btnText, grp) {
        const winBRect = this.helpDiv.node().getBoundingClientRect(),
            textBRect = btnText.node().getBoundingClientRect(),
            grpBRect = grp.node().getBoundingClientRect();

        const vertOffset = 7;

        const coords = {
            ul: { x: textBRect.right - winBRect.left + 5, y: textBRect.top - winBRect.top + vertOffset },
            ur: { x: grpBRect.left - winBRect.left, y: grpBRect.top - winBRect.top + 0.5 },
            bl: { x: textBRect.right - winBRect.left + 5, y: textBRect.bottom - winBRect.top - vertOffset },
            br: { x: grpBRect.left - winBRect.left, y: grpBRect.bottom - winBRect.top - 0.5 }
        }

        const curve = {
            ul: { x: coords.ul.x + 5, y: coords.ul.y + 5 },
            bl: { x: coords.bl.x + 5, y: coords.bl.y - 5 }
        }

        const path = `M${coords.ur.x},${coords.ur.y} L${coords.ul.x},${coords.ul.y} ` +
            `C${curve.ul.x},${curve.ul.y} ${curve.bl.x},${curve.bl.y} ${coords.bl.x},${coords.bl.y} ` +
            `L${coords.br.x},${coords.br.y}`

        this.helpSvg.append('path').attr('d', path).attr('class', 'help-line');
    }
}
