/**
 * Polyfill for adding `submitter` support for the SubmitEvent
 * (https://developer.mozilla.org/en-US/docs/Web/API/SubmitEvent/submitter).
 */
!function(){
    var lastBtn = null
    document.addEventListener('click',function(e){
        if (!e.target.closest) return;
        lastBtn = e.target.closest('button, input[type=submit]');
    }, true);
    document.addEventListener('submit',function(e){
        if (e.submitter) return;
        var canditates = [document.activeElement, lastBtn];
        for (var i=0; i < canditates.length; i++) {
            var candidate = canditates[i];
            if (!candidate) continue;
            if (!candidate.form) continue;
            if (!candidate.matches('button, input[type=button], input[type=image]')) continue;
            e.submitter = candidate;
            return;
        }
        e.submitter = e.target.querySelector('button, input[type=button], input[type=image]')
    }, true);
}();

/**
 * Provides the ability to embed Lightning Components into Visualforce pages / components in Community Hub.
 * Makes the assumption that an <apex:includeLightning /> tag is already present in the page stack.
 */
(function(w){
    var communityHubLightningEmbedderMethods = {
        'embedComponent': embedComponent
    };

    var communityHubEmbeddedComponents = new Map();

    /**
     * Loads a Lightning Component into the page dynamically.
     * @param {string} appName - The name of a Lightning App container which will hold this component. Must be global.
     * @param {object} config - JSON object containing the configuration.
     *        A minimum viable example is provided here:
     *        {
     *            "ComponentName": "c:Demo", // The name of the Lightning Component we wish to embed. WITH namespace.
     *            "Attributes": { // Zero or more attributes pertaining to the Lightning Component. Must be present.
     *                "example": "hello" // This would be a public attribute on the Lightning Component.
     *            },
     *            "Callback": function (createdComponent) {
     *                // Do something with createdComponent...
     *            }
     *        }
     * @param {string} containerId - The name of an HTML element which will contain the Lightning Component on the page.
     */
    function embedComponent(appName, config, containerId) {
        // Validate that there is no error present in the config.
        if (config.Error !== undefined && config.Error !== null && config.Error !== '') {
            let container = document.getElementById(containerId);
            container.innerHTML = config.Error;
            return;
        }

        // Prevent the same config from being embedded twice in the same container.
        if (typeof communityHubEmbeddedComponents.get(containerId) !== 'undefined') {
            return;
        }

        communityHubEmbeddedComponents.set(containerId, config.ComponentName);

        $Lightning.use(appName, function() {
            $Lightning.createComponent(config.ComponentName, config.Attributes || {}, containerId, function(cmp) {
                if (typeof config.Callback === 'function') {
                    config.Callback(cmp);
                }

                if (config.PreventFormSubmit) {
                    const embedContainer = document.getElementById(containerId);
                    const lwcRoot = cmp.elements[0].shadowRoot;
                    const config = { attributes: false, childList: true, subtree: true };

                    const observer = new MutationObserver(function(mutationsList) {
                        embedContainer.querySelectorAll('button.slds-button').forEach(button => {
                            // Do not override existing type attributes.
                            if (null === button.getAttribute('type')) {
                                button.setAttribute('type', 'button');
                            }
                        });
                    });

                    observer.observe(lwcRoot, config);
                }

                $A.eventService.addHandler({
                    event: 'force:navigateToURL', handler: function(handledEvt) {
                        window.location.replace(handledEvt.getParam('url'));
                        return false;
                    }
                });
            });
        });
    }

    w.ncLightningEmbedder = communityHubLightningEmbedderMethods;
})(window);