// ==UserScript==
// @name        Import Boomkat releases to Musicbrainz
// @description Add a button on Boomkat release pages to open MusicBrainz release editor with pre-filled data for the selected release
// @version     2024.09.10.1
// @license     X11
// @downloadURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/boomkat_importer.user.js
// @updateURL   https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/boomkat_importer.user.js
// @namespace   https://github.com/murdos/musicbrainz-userscripts
// @include     https://boomkat.com/products/*
// @require     lib/mbimport.js
// @require     lib/logger.js
// @require     lib/mbimportstyle.js
// ==/UserScript==

async function onLoad() {
    MBImportStyle();

    const release_url = window.location.href.replace('/?.*$/', '').replace(/#.*$/, '');
    await fetchTracksAndInsertLink(release_url);

    // Update the release info when a different tab/format is
    // selected. We pass the event target down to fetchTracksAndInsertLink
    // so we can easily fetch the format type from the clicked link.
    // Without this, we'd need to resort to delays which are... inconsistent
    // on Boomkat.
    document.querySelectorAll('ul.tabs li.tab-title a').forEach(function (elem) {
        elem.addEventListener('click', async function (event) {
            await fetchTracksAndInsertLink(release_url, event.target);
        });
    });
}

function getFormat(format) {
    if (format.match(/MP3|WAV|FLAC/i)) {
        return 'Digital Media';
    }

    if (format.match(/CD/i)) {
        return 'CD';
    }

    if (format.match(/LP|12"/i)) {
        return 'Vinyl';
    }

    if (format.match(/CASSETTE/i)) {
        return 'Cassette';
    }

    return '';
}

function getLinkType(media) {
    if (media == 'Digital Media') {
        return MBImport.URL_TYPES.purchase_for_download;
    }
    return MBImport.URL_TYPES.purchase_for_mail_order;
}

async function fetchTracksAndInsertLink(release_url, formatElement) {
    const release = await retrieveReleaseInfo(release_url, formatElement);
    insertLink(release, release_url);
}

async function retrieveReleaseInfo(release_url, formatElement) {
    const releaseDateStr = document.querySelector('span.release-date-placeholder').textContent.replace('Release date: ', '');
    const releaseDate = new Date(releaseDateStr);
    const artist = document.querySelector('h1.detail--artists').textContent.trim();

    const release = {
        artist_credit: MBImport.makeArtistCredits([artist]),
        title: document.querySelector('h2.detail_album').textContent.trim(),
        year: releaseDate.getUTCFullYear(),
        month: releaseDate.getUTCMonth() + 1,
        day: releaseDate.getUTCDate(),
        country: 'XW',
        status: 'official',
        language: 'eng',
        script: 'Latn',
        type: '',
        urls: [],
        labels: [],
        discs: [],
    };

    // Labels
    release.labels.push({
        name: document.querySelector('span.label-placeholder a').textContent,
        catno: document.querySelector('span.catalogue-number-placeholder').textContent.replace(/Cat No:/, ''),
    });

    // Format/packaging
    let format;
    if (formatElement != null) {
        format = formatElement.textContent.trim();
    } else {
        format = document.querySelector('ul.tabs .tab-title.active a').textContent.trim();
    }
    release.format = getFormat(format);
    release.packaging = release.format == 'Digital Media' ? 'None' : '';

    // URLs
    release.urls.push({
        url: release_url,
        link_type: getLinkType(release.format),
    });

    // Tracks
    // Boomkat loads the tracklist dynamically. Using setTimeout()
    // here is not consistent for reasons I have not yet figured out.
    // For now, just fetch the tracks the same way Boomkat does.
    const releaseID = document.querySelector('a.play-all').dataset.audioPlayerRelease;
    const tracklistURL = `https://boomkat.com/tracklist/${releaseID}`;
    const tracks = [];
    const response = await fetch(tracklistURL);
    const body = await response.text();
    const doc = document.implementation.createHTMLDocument('');
    doc.body.innerHTML = body;
    doc.querySelectorAll('div.table-row.track.mp3.clearfix a').forEach(function (link) {
        tracks.push({
            artist_credit: MBImport.makeArtistCredits([link.dataset.artist]),
            title: link.dataset.name,
            duration: link.dataset.duration,
        });
    });
    release.discs.push({
        tracks: tracks,
        format: release.format,
    });
    LOGGER.info('Parsed release: ', release);
    return release;
}

// Insert button into page
function insertLink(release, release_url) {
    // Remove any existing buttons
    document.querySelectorAll('.musicbrainz-import').forEach(function (elem) {
        elem.remove();
    });

    const edit_note = MBImport.makeEditNote(release_url, 'Boomkat');

    const div = document.createElement('div');
    div.className = 'product-note';

    const formButton = document.createElement('span');
    formButton.className = 'tab-title musicbrainz-import';
    formButton.innerHTML = MBImport.buildFormHTML(MBImport.buildFormParameters(release, edit_note));
    formButton.style.display = 'inline-block';

    const searchButton = document.createElement('span');
    searchButton.className = 'tab-title musicbrainz-import';
    searchButton.innerHTML = MBImport.buildSearchButton(release);
    searchButton.style.display = 'inline-block';

    div.appendChild(formButton);
    div.appendChild(searchButton);

    const albumHeader = document.querySelector('h2.detail_album');
    albumHeader.after(div);
}

if (document.readyState !== 'loading') {
    onLoad();
} else {
    document.addEventListener('DOMContentLoaded', onLoad);
}