/*!
 * 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 { getAds } from '../api/eclipsefdn.newsroom';
import loadingTemplate from './templates/loading-icon.mustache';
import defaultTemplate from './templates/promotion/default.mustache';
import renderTemplate from './templates/render-template';

/** 
  * Reduce the ad elements into an object containing the formats and
  * publishTo.
  *
  * @param {Object} acc - The accumulator.
  * @param {Object} acc.formats - The ad formats (e.g. { ads_square: '1' }).
  * @param {string} acc.publishTo - The ad publishTo (e.g. 'eclipse_org').
  * @param {Object} adElement - The ad element.
  * @returns {Object} - The accumulator.
  */
const adsInfoReducer = ({ formats, publishTo }, adElement) => {
  const options = adElement.dataset;
  
  // Validate the options.
  if (!options.adFormat) {
    console.error('The `data-ad-format` attribute is required for eclipsefdn-promo-content.');
    return { formats, publishTo };
  }

  if (!options.adPublishTo) {
    console.error('The `data-ad-publish-to` attribute is required for eclipsefdn-promo-content.');
    return { formats, publishTo };
  }

  // Add the options to the accumulator.
  return { 
    formats: { 
      ...formats, 
      // Set the format to 1. This is required by the API.
      ...{ [options.adFormat]: '1' }
    }, 
    // Overwrite the previous publishTo. All ads on page should have the same
    // value anyways.
    publishTo: options.adPublishTo
  };
}

const templates = {
  default: defaultTemplate,
};

/** 
  * Renders ad content.
  */
const render = async () => {
  const elements = Array.from(document.querySelectorAll('.eclipsefdn-promo-content'));
  if (elements.length === 0) return;
  
  elements.forEach(element => element.innerHTML = loadingTemplate());
  
  // Reduce the ad elements into an object containing the formats and
  // publishTo.
  const initialAdsInfo = { formats: {}, publishTo: null };
  const { formats, publishTo } = elements.reduce(adsInfoReducer, initialAdsInfo);

  // Fetch the ads
  const [ads, error] = await getAds({   
    publishTo,
    formats,
  });

  if (error) {
    console.error('An error occured while fetching the ads.');
    return;
  }

  // Get an array of promises. These promises are resolved once the template
  // has been fully rendered.
  const renderStatuses = ads.map(async (ad) => {
    elements.map(async (element) => {
      if (element.dataset.adFormat.includes(ad.format) && ad.url && ad.campaignName && ad.image) {
        await renderTemplate({
          element, 
          templates, 
          templateId: 'default', 
          data: ad
        });
      }
    });
  });
  
  // Returns a promise which resolves when the rendering of all ads has
  // completed.
  return Promise.all(renderStatuses);
};

export default { render };
