/*
 * Copyright (c) 2023 Eclipse Foundation, Inc.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * Contributors:
 *   Olivier Goulet <olivier.goulet@eclipse-foundation.org>
 *
 * SPDX-License-Identifier: EPL-2.0
 */

import Mustache from 'mustache';

/**
 * Renders the specified template into the given `element`
 *
 * @param {HTMLElement} element The element into which the template should be rendered.
 * @param {Object<string, (data?: any) => string>} templates An object containing named templates,
 * where the keys are template IDs and the values are functions that return HTML for the template.
 * @param {string} templateId Id of the template to render.
 * @param {any} data Data used by the template.
 * @returns {Promise<undefined>} A promise that resolves when the template has been rendered.
 */
const renderTemplate = (element, templates, templateId, data) => {
  return new Promise(resolve => {
    // Resolve once children of element have been mutated
    const observer = new MutationObserver(() => {
      observer.disconnect();
      resolve();
    });
    observer.observe(element, {
      childList: true,
    });

    // Determine which template to add to innerHTML
    const template = templates[templateId];

    const isUsingCustomTemplate = !template && document.getElementById(templateId) !== null;
    if (isUsingCustomTemplate) {
      const customTemplate = document.getElementById(templateId).innerHTML;
      element.innerHTML = Mustache.render(customTemplate, data);
      return;
    }

    if (!isUsingCustomTemplate && !template) {
      const msg = `Template ${templateId} has not been found.\n\nIf this is a custom template, make sure you spelled the template name correctly.\n\nIf using a custom template was not your intention, use one of the following templates:${Object.keys(
        templates
      ).map(tpl => `\n\t- ${tpl}`)}`;
      console.error(msg);
      
      observer.disconnect();
      resolve();
      return;
    }

    element.innerHTML = template(data);
  });
};

export default renderTemplate;
