import { ready } from '../../utilities/ready';

const contentVariations = (function (exports) {
	'use strict';

	let variationBlocks = []; // Track the variation blocks

	// Web Component for ContentVariations
	class PWPContentVariations extends HTMLElement {
		connectedCallback() {
			// Check if we have a blockId
			if (this.blockId) {
				// Push the element to the variationBlocks array
				variationBlocks.push(this);
			}
		}

		get blockId() {
			return this.getAttribute("variations-block-id");
		}
	}
	window.customElements.define('pwp-content-variations', PWPContentVariations);

	/**
	 * Parse DOM placeholders for Content Variation blocks
	 */
	async function populateVariations() {
		const { getBlocks } = PersonalizeWP;
		const { nodeScriptReplace } = PersonalizeWP.utils;

		// Pre-process the variationBlocks data to simplify before sending to the API
		let blockIDs = [];
		for (let block of variationBlocks) {
			blockIDs.push(block.blockId);
		};

		// Double check something to work with
		if (0 === blockIDs.length) {
			return;
		}

		getBlocks( blockIDs, 'v1/variation-blocks')
			.then((replacements) => {
				if (!Array.isArray(replacements)) {
					throw "No replacements to parse";
				}
				// Post-process the data to group the original element with the content to show
				const batch = [];
				for(let replacement of replacements) {
					// process elements in order
					const el = variationBlocks.shift();
					// do we have respective element content? Assume 1 to 1 relationship
					if (replacement) {
						batch.push([el, replacement]);
					}
					else {
						// Simply remove our own container, leaving the fallback content direct in DOM
						el.replaceWith( ...el.childNodes );
					}
				};

				if (batch.length) {
					// replace web component element with real content
					for(let b of batch) {
						const placeholderContainer = b[0].parentNode;
						// We don't know what the actual HTML is, so use a generic one to place everything within for now. This'll be removed later.
						let el = document.createElement("div");
						// Set the inner content of the div. This sets the API response as a string and is parsed as DOM elements, but doesn't process scripts.
						el.innerHTML = b[1];
						// Re-Process the element to restore any <script>s
						el = nodeScriptReplace(el);

						// Replace the web component placeholder in the DOM with the new elements' children, as there could be many elements.
						b[0].replaceWith(...el.childNodes);

						// Allow triggering functionality when individual blocks are inserted.
						const blockEvent = new CustomEvent('PWP:parsePlaceholder', {
							bubbles: true,
							cancelable: true,
							detail: {
								container: placeholderContainer,
							},
						});
						placeholderContainer.dispatchEvent(blockEvent);
					};

					// Re-trigger standard browser event for any setup that plugins might be doing.
					document.dispatchEvent(new CustomEvent('DOMContentLoaded'));

					// Allow triggering functionality when batches of blocks are inserted.
					const batchEvent = new CustomEvent('PWP:parsedPlaceholders', {
						bubbles: true,
						cancelable: true,
					});
					document.dispatchEvent(batchEvent);
				}
			})
			.catch((err) => {
				console.log(err);
			});
	}

	/**
	 * Called automatically by PersonalizeWP after module has been initiated.
	 */
	function moduleReady() {
		populateVariations();
	}

	/**
	 * Called automatically once PersonalizeWP is available for loading this module.
	 */
	function readyInit() {
		// Double check
		if ( window.PersonalizeWP ) {
			PersonalizeWP.module('content-variations', this);
		}
	}

	// Export the public functions of Content Variations
	exports.ready = moduleReady;
	exports.readyInit = readyInit;

	return exports;
})({});

// Check and delay until PersonalizeWP object available.
ready(contentVariations);
