/**
 * @jest-environment jsdom
 */

/*
 * 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 eclipsefdnVideoList from '../eclipsefdn.video-list';
import * as mediaLinkModule from '../../api/eclipsefdn.media-link';
import { playlists as playlistsMock } from './mocks/eclipsefdn.video-list-mock-data';

describe('eclipsefdn-video-list', () => {
  let getPlaylistsSpy;

  beforeEach(() => {
    getPlaylistsSpy = jest.spyOn(mediaLinkModule.youtube, 'getPlaylists');
  });

  it("Don't render video list without playlist ids and log error", async () => {
    const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

    document.querySelector('body').innerHTML = `
            <div class="eclipsefdn-video-list"></div>
        `;

    eclipsefdnVideoList.render();

    // Expect a loading spinner to display
    const loadingElement = document.querySelector('.fa-spinner');
    expect(loadingElement).toBeDefined();

    // Ensure that no video list items are shown
    const videoListElements = document.querySelectorAll('.video-list-item');
    expect(videoListElements.length).toBe(0);

    // Ensure the proper error message is displayed
    expect(consoleSpy).toHaveBeenCalledWith('No playlist id(s) provided');
    consoleSpy.mockRestore();
  });

  it('Render playlist item when a single playlist id is provided', async () => {
    const playlistId = 'PLy7t4z5SYNaTxmWWrnLYshYKaSLhRKNk-';
    getPlaylistsSpy.mockReturnValue([playlistsMock.filter(p => p.id === playlistId), null]);

    document.querySelector('body').innerHTML = `
            <div 
                class="eclipsefdn-video-list" 
                data-playlist-ids="${playlistId}"
            >
            </div>
        `;

    await eclipsefdnVideoList.render();

    // Ensures that the correct playlist id is given to the api function
    expect(getPlaylistsSpy).toHaveBeenCalledWith([playlistId]);

    // Ensures that only one video list item is present
    const videoListElements = document.querySelectorAll('.video-list-item');
    expect(videoListElements.length).toBe(1);

    getPlaylistsSpy.mockRestore();
  });

  it('Renders multiple playlists when multiple playlist ids are provided', async () => {
    const playlistIds = [playlistsMock[0].id, playlistsMock[1].id];
    const matchingPlaylistMocks = playlistsMock.filter(p => playlistIds.includes(p.id));

    getPlaylistsSpy.mockReturnValue([matchingPlaylistMocks, null]);

    document.querySelector('body').innerHTML = `
            <div
                class="eclipsefdn-video-list"
                data-playlist-ids="${playlistIds.join(',')}"
            >
            </div>
        `;

    await eclipsefdnVideoList.render();

    // Ensures that the correct playlist ids were given to the api function
    expect(getPlaylistsSpy).toHaveBeenCalledWith(playlistIds);

    // Ensures that the correct number of video list items were rendered
    const videoListElements = document.querySelectorAll('.video-list-item');
    expect(videoListElements.length).toBe(playlistIds.length);

    // Ensure that the correct video list items were listed by comparing titles
    const videoListTitles = new Set(
      Array.from(document.querySelectorAll('.video-details-title')).map(
        titleElement => titleElement.textContent
      )
    );
    expect(videoListTitles).toEqual(new Set(matchingPlaylistMocks.map(p => p.title)));

    getPlaylistsSpy.mockRestore();
  });

  it('Modify the max length of the descriptions of video list items', async () => {
    // Overwrite the mock data description in-case the mock data changes. 
    // We don't want this test to break if playlistsMock[0] were to change.
    const playlistMock = {
      ...playlistsMock[0],
      description: 'This is a short description for a video list item',
    };

    getPlaylistsSpy.mockReturnValue([[playlistMock], null]);

    const descriptionMaxLength = 30;

    document.querySelector('body').innerHTML = `
            <div
                class="eclipsefdn-video-list"
                data-playlist-ids="${playlistMock.id}"
                data-description-max-length="${descriptionMaxLength}"
            >
            </div>
        `;

    await eclipsefdnVideoList.render();

    const descriptionElement = document.querySelector('.video-details-description');

    // Ensures that the description is the correct length including an ellipsis
    expect(descriptionElement.textContent).toEqual(
      playlistMock.description.substring(0, descriptionMaxLength - 3).concat('...')
    );
  });
});
