/*!
 * Copyright (c) 2021, 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:
 *   Eric Poirier <eric.poirier@eclipse-foundation.org>
 *   Olivier Goulet <olivier.goulet@eclipse-foundation.org>
 *
 * SPDX-License-Identifier: EPL-2.0
 */

import 'isomorphic-fetch';
import { getNextPage, transformSnakeToCamel } from '../utils/utils';

const apiBasePath = 'https://newsroom.eclipse.org/api';

/**
  * @param {Object} params
  * @param {number} params.pageSize
  * @param {string[] | undefined} params.resourceTypes The resource types to be retrieved. Ex. 'case_study', 'social_media_kit', 'white_paper'. 
  * @param {string[] | undefined} params.publishTo The publishing destinations to be retrieved. Ex. 'eclipse_org'.
  * @returns {Promise}
*/
export const getNewsroomResources = async ({ pageSize, resourceTypes, publishTo } = {}) => {
  try {
    const url = new URL(`${apiBasePath}/resources`);
    resourceTypes && resourceTypes.forEach(t => url.searchParams.append('parameters[resource_type][]', t));
    publishTo && publishTo.forEach(p => url.searchParams.append('parameters[publish_to][]', p));
    pageSize && url.searchParams.append('pagesize', pageSize);

    let newsroomResources = [];

    let nextPage = url;
    while (nextPage) {
      const response = await fetch(nextPage.href);
      if (!response.ok) throw new Error('Could not fetch newsroom resources');

      const data = await response.json();
      if (data && data.resources) { 
        newsroomResources = newsroomResources.concat(data.resources);
      }

      // If `pageSize` is set and the current amount of newsroom resources surpasses it, break the loop.
      // We may still have extra newsroom resources going over the limit but at least we won't fetch any more.
      // Extra newsroom resources will be removed later.
      if (pageSize && newsroomResources.length >= pageSize) break;

      const linkHeader = response.headers.get('Link');
      nextPage = getNextPage(linkHeader);
    }

    // If pageSize is set, remove the extra newsroom resources.
    if (pageSize) {
      newsroomResources.splice(pageSize);
    }

    return [newsroomResources, null];
  } catch (error) {
    console.error(error);

    return [null, error];
  }
}

/**
  * @typedef {('ads_square'|'ads_leaderboard'|'ads_top_leaderboard'|'ads_download')} AdFormat
  */

/**
  * @typedef {Partial<Record<AdFormat, string>>} FormatOptions - The options to
  * be used when retrieving ads.
  */

/**
  * Retrieve ads for a specified website.
  *
  * @param {Object} options - The options to be used when retrieving ads.
  * @param {string} options.publishTo - The website to retrieve ads for. Ex.
  * 'eclipse_org'.
  * @param {FormatOptions} options.formats - The formats of the ads to be
  * retrieved. Ex. 'ads_square'.
  */
export const getAds = async (options) => {
  try {
    if (!options.publishTo) throw new TypeError('Missing required option: publishTo');
    if (!options.formats) throw new TypeError('Missing required option: formats');

    const url = `${apiBasePath}/ads`;
    const payload = {
      host: window.location.host,
      source: window.location.pathname,
      publish_to: options.publishTo,
      format: options.formats,
    }

    // Make the request to the API.
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    });

    if (!response.ok) throw new Error('Could not fetch ads');

    const data = await response.json();
    const ads = transformSnakeToCamel(data); 
    
    return [ads, null];
  } catch (error) {
    return [null, error];
  }
};
