"use strict";

/**
 * @name Generator
 *
 * @description
 *
 * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
export default class generator {
	/**
	 * @name Print (interface)
	 *
	 * @description
	 * Request to generate image and receive image for printing
	 *
	 * @param {string} type Type (37mm)
	 * @param {number} [amount=1] Amount
	 * @param {HTMLElement} canvas The canvas with images
	 * @param {HTMLElement} button Button
	 * @param {boolean} [force=false] Ignore the damper?
	 *
	 * @return {boolean} Did the processing complete without errors?
	 */
	static print(type, amount = 1, canvas, button, force = false) {
		core.modules.connect("damper").then(
			() => {
				// Imported the damper module

				// Processing under damper
				generator.print.damper(type, amount, canvas, button, force);
			},
			() => {
				// Not imported the damper module

				// Processing
				generator.print.system(type, amount, canvas, button);
			},
		);

		// Exit (success)
		return true;
	}
}

core.modules.connect("damper").then(() => {
	// Imported the damper module

	Object.assign(
		generator.print,
		{
			/**
			 * @name Print (damper)
			 *
			 * @description
			 * Request to generate image and receive image for printing
			 *
			 * @memberof generator.print
			 *
			 * @param {string} type Type (37mm)
			 * @param {number} [amount=1] Amount
			 * @param {HTMLElement} canvas The canvas with images
			 * @param {HTMLElement} button Button
			 * @param {boolean} [force=false] Ignore the damper?
			 *
			 * @return {void}
			 */
			damper: core.global.damper(
				(...variables) => generator.print.system(...variables),
				300,
				4,
			),
		},
	);
});

Object.assign(
	generator.print,
	{
		/**
		 * @name Print (system)
		 *
		 * @description
		 * Request to generate image and receive image for printing
		 *
		 * @memberof generator.print
		 *
		 * @param {string} type Type (37mm)
		 * @param {number} [amount=1] Amount
		 * @param {HTMLElement} canvas The canvas with images
		 * @param {HTMLElement} button Button
		 * @param {function} resolve Resolve
		 * @param {function} reject Reject
		 *
		 * @return {Promise} Request to the server
		 */
		async system(
			type,
			amount = 1,
			canvas,
			button,
			resolve = () => {},
			reject = () => {},
		) {
			try {
				if (
					typeof type === "string" &&
					type.length > 0 &&
					typeof amount === "number" &&
					canvas instanceof HTMLElement
				) {
					// Validated all required arguments

					// Initializing the body buffer
					const body = new FormData();

					// Writing parameters into the body buffer
					body.append("type", type);

					// Initializing the canvas JSON buffer
					/* const canvas = {
						width: 
					};
 */
					// const background = ;

					// Writing canvas into the body buffer
					body.append("canvas", JSON.stringify({
						width: canvas.clientWidth,
						height: canvas.clientHeight
					}));

					//
					// Iterating over products

					// Initializing the product JSON buffer
					const product = {};

					for (const layer of canvas.querySelectorAll("div.layer")) {
						// Iterating over layers

						// Initializing the layer index
						const index = +layer.getAttribute("id")?.split(
							"pechatalka_layer_",
						)[1];

						if (typeof index === "number") {
							// Initialized the layer index

							// Initializing the layer
							product[index] ??= {};

							// Writing the layer parameters
							product[index].x =
								parseInt(layer.style.getPropertyValue("left")) || 0;
							product[index].y =
								parseInt(layer.style.getPropertyValue("top")) || 0;
							product[index].scale = parseFloat(layer.style.getPropertyValue("scale") || 1);

							// Initializing the layer type
							const type = layer.getAttribute("data-layer-type");

							if (type === "image") {
								// Image

								// Initializing the layer image
								const image = layer.getElementsByTagName("img")[0];

								if (image instanceof HTMLImageElement) {
									// Initialized the layer image

									// Initializing the image `src` attribute value
									const src = image.getAttribute("src")?.split("?")[0];

									if (src.length > 0) {
										// Initialized the image `src` attribute value

										if (new URL(src).protocol === "blob:") {
											// Blob

											await fetch(src).then((r) => r.blob()).then((value) => {
												// Converted "blob:..." string to the Blob object

												// Writing into the body buffer (`{$product}_{$layer}`)
												body.append("0_" + index, value, index);
											});
										} else {
											// URL (expected)

											// Writing the layer parameter
											product[index].image = src;
										}
									}
								}
							} else if (type === "film") {
								// Film (laminating)
							}
						}
					}

					// Writing products into the body buffer (the only one canvas)
					body.append("products", JSON.stringify({0: product}));

					return await core.request(
						"/generator/print",
						body,
						"POST",
						{},
						null,
					).then(
						async (json) => {
							if (json) {
								// Received a JSON-response

								if (
									json.errors !== null &&
									typeof json.errors === "object" &&
									json.errors.length > 0
								) {
									// Fail (received errors)

									// Exit (fail)
									reject(json);
								} else {
									// Success (not received errors)

									// Exit (success)
									resolve();
								}
							}
						},
						() => reject(),
					);
				}
			} catch (e) {
				// Exit (fail)
				reject(e);
			}
		},
	},
);
