import * as noise from "./simplex-noise.mjs";

("use strict");

/**
 * @name womb3-simplex.mjs
 *
 * @description
 * The library for creating creepy sticky background
 *
 * @class
 * @public
 *
 * {@link https://git.svoboda.works/mirzaev/womb3-simplex.mjs}
 * {@link https://codepen.io/mirzaev-sexy/pen/BaxQjYo}
 *
 * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
export class womb {
	noise = new noise.createNoise2D();

	constructor(shell) {
		if (typeof shell === "object") {
			// Получены входные параметры

			// Элемент для отрисовки
			this.shell = shell;

			// Поле отрисовки
			this.canvas = this.shell.getContext("2d");

			this.shell.width = document.body.offsetWidth;
			this.shell.height = document.body.offsetHeight;

			return this;
		}

		return null;
	}

	block = {
		width: 28,
		height: 28,
	};

	draw(x, y, color = "red", alpha) {
		// Запись цвета
		this.canvas.fillStyle = color;

		// Запись прозрачности
		this.canvas.globalAlpha = alpha;

		// Рисование на полотне
		this.canvas.fillRect(x, y, this.block.width, this.block.height);
	}

	restricted = [];

	clean(x, y, offset, to = 0, smooth = 0.3, ticks = 3) {
		// Инициализация актуального значения альфа-канала
		const alpha = 0.5 + this.noise(x + offset, y + offset) / 2;

		// Запись в реестр
		this.restricted.push({
			x,
			y,
			alpha,
			from: alpha,
			to,
			smooth,
			limit: ticks,
			ticks: 0,
		});
	}

	dump() {
		// Очистка полотна
		this.canvas.clearRect(0, 0, this.shell.width, this.shell.height);
	}

	init() {
		// Запись размеров полотна
		this.shell.width = document.body.offsetWidth;
		this.shell.height = document.body.offsetHeight;
	}

	generate(offset = 0, color = "red") {
		for (let y = 0; y < this.shell.height; y += this.block.height) {
			// Перебор колонок

			for (let x = 0; x < this.shell.width; x += this.block.width) {
				// Перебор строк

				// Рисование на полотне
				this.draw(
					x,
					y,
					color,
					0.5 + this.noise(x + offset, y + offset) / 2
				);
			}
		}
	}

	interactive(offset = 0, color = "red") {
		for (let y = 0; y < this.shell.height; y += this.block.height) {
			// Перебор колонок

			for (let x = 0; x < this.shell.width; x += this.block.width) {
				// Перебор строк

				// Инициализация альфа-канала
				let alpha = 0.5 + this.noise(x + offset, y + offset) / 2;

				for (const i in this.restricted) {
					// Перебор запрещённых блоков

					// Инициализация блока
					const block = this.restricted[i];

					if (x === block.x && y === block.y) {
						// Блок найден

						if (block.smooth === 0) {
							// Резкий переход

							if (block.ticks <= block.limit) {
								// Процесс "затухание"

								// Запись альфа-канала для рисования
								alpha = block.to;

								// Инкрементация значения тиков
								++block.ticks;
							} else {
								// Процесс "появление"

								// Запись альфа-канала для рисования
								alpha = block.from;

								// Удаление из массива запрещённых для рисования блоков
								delete this.restricted[i];
							}
						} else {
							// Плавный переход

							if (
								block.ticks < block.limit &&
								block.alpha - block.smooth > block.to
							) {
								// Процесс "затухание"

								// Запись нового значения альфа-канала
								block.alpha -= block.smooth;

								// Запись альфа-канала для рисования
								alpha = block.alpha;
							} else {
								// Завершён процесс "затухание"

								if (block.ticks < block.limit) {
									// Процесс "ожидание"

									// Инкрементация значения тиков
									++block.ticks;

									// Запись альфа-канала для рисования
									alpha = block.to;
								} else {
									// Завершён процесс "ожидание"

									if (
										block.ticks >= block.limit &&
										block.alpha + block.smooth < block.from
									) {
										// Процесс "появление"

										// Запись нового значения альфа-канала
										block.alpha += block.smooth;

										// Запись альфа-канала для рисования
										alpha = block.alpha;
									} else {
										// Завершён процесс "появление"

										// Запись альфа-канала для рисования
										alpha = block.from;

										// Удаление из массива запрещённых для рисования блоков
										delete this.restricted[i];
									}
								}
							}
						}
					}
				}

				this.draw(x, y, color, alpha);
			}
		}
	}
}

document.dispatchEvent(
	new CustomEvent("womb.loaded", {
		detail: { womb },
	})
);
