const puppeteer = require("puppeteer");

// Handle a few different cases since specialized pages use specialized classes.
const webampButtonSelector =
  ".js-webamp-use_skin_for_audio_items, .webamp-link";

// Create our own log function so we can mute it if we want
function log(message) {
  console.log(message);
}

const TIMEOUT = 10000;

async function expectSelector(page, selector) {
  log(`Waiting for selector ${selector}...`);
  await page.waitForSelector(selector, { visible: true, timeout: TIMEOUT });
  log(`Found selector ✅`);
}

async function testPage({ url, name, firstTrackText }) {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  try {
    log(`🏁 [${name}] ${url}`);
    await page.goto(url);
    await expectSelector(page, webampButtonSelector);
    log("Going to click the Webamp button");
    // For some reason `page.click` often fails with `Error: Node is either not
    // visible or not an HTMLElement` so we use `page.evaluate` instead.
    // https://stackoverflow.com/a/52336777
    // await page.click(webampButtonSelector, { timeout: TIMEOUT });
    await page.evaluate(() => {
      document
        .querySelector(".js-webamp-use_skin_for_audio_items, .webamp-link")
        .click();
    });
    await expectSelector(page, "#webamp #main-window");
    log("Looking for first track...");
    const firstTrack = await page.$(".track-cell.current");
    if (firstTrack == null) {
      throw new Error("Could not find first track");
    }
    log("Getting text of first track...");
    const actualFirstTrackText = await page.evaluate(
      _ => _.textContent,
      firstTrack
    );

    if (!actualFirstTrackText.includes(firstTrackText)) {
      throw new Error(
        `Could not find track title '${firstTrackText}' in "${actualFirstTrackText}"`
      );
    }

    log("Clicking play...");
    await page.click("#webamp #main-window #play", { timeout: TIMEOUT });
    await expectSelector(page, "#webamp #main-window.play");
    log("✅ Success! Test passed.");
  } catch (e) {
    log(`🛑 Errored in [${name}]. Wrote screenshot to ./error.png`);
    await page.screenshot({ path: "error.png", fullPage: true });
    throw e;
  } finally {
    log("DONE");
    await browser.close();
  }
}

async function testPageAndRetry(options) {
  let retries = 5;
  while (retries--) {
    try {
      await testPage(options);
      return;
    } catch (e) {
      console.error(e);
      if (retries > 0) {
        console.warn(`Retrying... ${retries} retries left.`);
      }
    }
  }
  throw new Error("Failed to pass even after 5 retries");
}

async function main() {
  await testPageAndRetry({
    name: "Popular",
    url: "https://archive.org/details/gd73-06-10.sbd.hollister.174.sbeok.shnf",
    firstTrackText: "Grateful Dead - Morning Dew",
  });
  await testPageAndRetry({
    name: "Regular",
    url:
      "https://archive.org/details/78_mambo-no.-5_perez-prado-and-his-orchestra-d.-perez-prado_gbia0009774b",
    firstTrackText: "Mambo No. 5",
  });
  await testPageAndRetry({
    name: "Samples Only",
    url:
      "https://archive.org/details/lp_smokey-and-the-bandit-2-original-soundtrac_various-brenda-lee-burt-reynolds-don-willi",
    firstTrackText: "Texas Bound And Flyin",
  });
  await testPageAndRetry({
    name: "Stream Only",
    url: "https://archive.org/details/cd_a-sweeter-music_sarah-cahill",
    firstTrackText: "Be Kind to One Another",
  });
  await testPageAndRetry({
    name: "Another",
    url:
      "https://archive.org/details/78_house-of-the-rising-sun_josh-white-and-his-guitar_gbia0001628b",
    firstTrackText: "House Of The Rising Sun",
  });
}

(async function() {
  try {
    await main();
  } catch (e) {
    console.error(e);
    // Ensure process returns an error exit code so that other tools know the test failed.
    process.exit(1);
  }
})();
