Source: display.js

/**
 * Manages the rendering and visual presentation of film and series content.
 *
 * This module provides functions to display popular items, individual films and series,
 * generate styled content cards, and handle empty result states. It also includes logic
 * to determine the type of content item and structure the corresponding HTML output.
 * All rendering is performed by injecting HTML into predefined container elements in the DOM.
 *
 * @module display
 */

/**
 * Displays the most popular films and series based on IMDb ratings.
 *
 * Sorts the film and series data by descending IMDb rating, selects the top six items
 * from each category, and renders them using the appropriate display container.
 *
 * @function
 */
function displayPopularContent() {
    const popularFilms = Object.values(filmsData)
        .sort((a, b) => (b.IMDb || 0) - (a.IMDb || 0))
        .slice(0, 6);

    const popularSeries = Object.values(seriesData)
        .sort((a, b) => (b.IMDb || 0) - (a.IMDb || 0))
        .slice(0, 6);

    displayContent(popularFilms, "popularFilms");
    displayContent(popularSeries, "popularSeries");
}

/**
 * Displays a list of film items in the films display grid.
 *
 * Sorts the provided films alphabetically by title, then renders them
 * in the DOM element with the ID "filmsGrid" using the displayContent function.
 *
 * @function
 * @param {Object[]} films - An array of film objects to display.
 */
function displayFilms(films) {
    const sortedFilms = films.slice().sort((a, b) => a.title.localeCompare(b.title));
    displayContent(sortedFilms, "filmsGrid");
}

/**
 * Displays a list of film items in the series display grid.
 *
 * Sorts the provided series alphabetically by title, then renders them
 * in the DOM element with the ID "seriesGrid" using the displayContent function.
 *
 * @function
 * @param {Object[]} series - An array of series objects to display.
 */
function displaySeries(series) {
    const sortedSeries = series.slice().sort((a, b) => a.title.localeCompare(b.title));
    displayContent(sortedSeries, "seriesGrid");
}

/**
 * Displays a list of content items in the specified container.
 *
 * Retrieves the DOM element by its ID and populates it with content cards generated
 * from the provided items. If the container is not found or the items array is empty,
 * a "no results" message is displayed instead.
 *
 * @function
 * @param {Object[]} items - An array of content objects to display (e.g., films or series).
 * @param {string} containerId - The ID of the DOM element where the content should be rendered.
 */
function displayContent(items, containerId) {
    const container = document.getElementById(containerId);
    if (!container) return;

    if (!items || items.length === 0) {
        container.innerHTML = '<div class="no-results"><i class="fas fa-film"></i><p>Aucun contenu trouvé</p></div>';
        return;
    }

    container.innerHTML = items.map((item) => createContentCard(item)).join("");
}

/**
 * Creates an HTML content card for a given item (film or series).
 *
 * Builds a styled card element containing the item's title, banner image, genres,
 * release year, IMDb rating, and a badge indicating whether it has been fully watched.
 * The card includes an onclick handler to open a modal with detailed information.
 *
 * @function
 * @param {Object} item - The content item to render (must include title, genres, year, IMDb rating, and optionally a banner).
 * @returns {string} A string of HTML representing the content card.
 */
function createContentCard(item) {
    const genres = item.genres ? item.genres
        .slice(0, 3)
        .map((g) => `<span class="genre-tag">${g}</span>`)
        .join("") : "";
    const rating = item.IMDb ? `<div class="card-rating"><i class="fas fa-star"></i> ${item.IMDb}</div>` : "";
    const year = item.year ? `<span class="card-year">${item.year}</span>` : "";

    let watchedBadge = "";
    if (getItemType(item) === "film") {
        const watchData = getFilmWatchData(item.title);
        if (watchData.watched) {
            watchedBadge = `<span class="watched-badge" title="Déjà vu"><i class="fas fa-eye"></i></span>`;
        }
    } else if (getItemType(item) === "series") {
        if (isSeriesFullyWatched(item)) {
            watchedBadge = `<span class="watched-badge" title="Série vue en entier"><i class="fas fa-eye"></i></span>`;
        }
    }

    return `
      <div class="content-card" onclick="openModal('${escapeForHTML(item.title)}', '${getItemType(item)}')">
        <div class="card-image">
          ${item.banner ? `<img src="${item.banner}" alt="${item.title}" onerror="this.style.display='none'">` : '<i class="fas fa-film"></i>'}
          ${watchedBadge}
        </div>
        <div class="card-content">
          <h3 class="card-title">${item.title}</h3>
          <div class="card-meta">
            ${rating}
            ${year}
          </div>
          <div class="card-genres">${genres}</div>
        </div>
      </div>
    `;
}

/**
 * Determines the type of content item based on its properties.
 *
 * Checks whether the item has a "seasons" property to classify it as a series;
 * otherwise, it is considered a film.
 *
 * @function
 * @param {Object} item - The content item to evaluate.
 * @returns {string} Returns "series" if the item has seasons, otherwise "film".
 */
function getItemType(item) {
    return item.seasons ? "series" : "film";
}

/**
 * Generates an HTML block displaying a "no results" message.
 *
 * Returns a styled HTML string containing an icon and a message, used when no content matches the user's search or filter criteria.
 *
 * @function
 * @param {string} [message="Aucun résultat trouvé"] - The message to display.
 * @returns {string} An HTML string representing the "no results" message.
 */
function showNoResults(message = "Aucun résultat trouvé") {
    return `
    <div class="no-results">
      <i class="fas fa-search"></i>
      <p>${message}</p>
    </div>
  `;
}