import { createNoise2D } from "simplex-noise";
import { createCanvas, ImageData } from "canvas";
import alea from "alea";

const SEED = "runtimefee.lol";
var log_once = false;

/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
export default function (eleventyConfig) {
	// Directory configs
	eleventyConfig.setInputDirectory("content");
	eleventyConfig.setIncludesDirectory("../_includes"); // relative to the input directory, therefore the ../
	eleventyConfig.setDataDirectory("../_data"); // relative to the input directory, therefore the ../
	eleventyConfig.setOutputDirectory("_site");

	eleventyConfig.setFrontMatterParsingOptions({
		excerpt: true,
		// Optional, default is "---"
		excerpt_separator: "<!-- excerpt -->",
	});

	// Custom date filter
	eleventyConfig.addFilter("date", (dateObj) => {
		return new Intl.DateTimeFormat("de-DE", {
			day: "numeric",
			month: "long",
			year: "numeric",
		}).format(dateObj);
	});

	eleventyConfig.addFilter("capitalize", function (value) {
		return value.toUpperCase();
	});

	// generate a nice preview image for articles that don't have one
	eleventyConfig.addShortcode("generateThumbnail", function (hash) {
		return getThumbnailImage(hash);
	});

	// Collections
	eleventyConfig.addCollection("posts", (collectionApi) => {
		return collectionApi.getFilteredByTag("posts");
	});

	eleventyConfig.addPassthroughCopy({ "public/": "/" });
}

function getRandomFloat(min, max) {
	return parseFloat((Math.random() * (max - min) + min).toFixed(2));
}

function getRandomPaletteValues() {
	// Generate random arrays for a, b, c, and d
	const a = [
		getRandomFloat(0.5, 1.0),
		getRandomFloat(0.5, 1.0),
		getRandomFloat(0.5, 1.0),
	];
	const b = [
		getRandomFloat(0.2, 0.8),
		getRandomFloat(0.2, 0.8),
		getRandomFloat(0.2, 0.8),
	];
	const c = [
		getRandomFloat(0.0, 2.0),
		getRandomFloat(0.0, 2.0),
		getRandomFloat(0.0, 2.0),
	];
	const d = [
		getRandomFloat(0.0, 1.0),
		getRandomFloat(0.0, 1.0),
		getRandomFloat(0.0, 1.0),
	];

	if (log_once == false) {
		log_once = true;
		//console.log({ a, b, c, d });
	}

	return { a, b, c, d };
}

function getPalette(t, a, b, c, d) {
	const result = [];

	for (let i = 0; i < 3; i++) {
		// Apply the formula element-wise to each component of the vectors
		result[i] =
			255 * (a[i] + b[i] * Math.cos(2.0 * Math.PI * (c[i] * t + d[i])));
	}

	if (log_once == false) {
		log_once = true;
		//console.log(result);
	}

	return result;
}

function getThumbnailImage(hash) {
	var width = 800;
	var height = 300;
	var rng = alea(SEED + hash);

	var noise2D = createNoise2D(rng);

	const canvas = createCanvas(width, height);
	const ctx = canvas.getContext("2d");
	const imageData = ctx.createImageData(width, height);
	const paletteSettings = getRandomPaletteValues();

	var dist = 0;
	for (let x = 0; x < width; x++) {
		for (let y = 0; y < height; y++) {
			const value = noise2D(x / 50, y / 50);
			var threshold = Math.floor((value + 1) * 128);
			threshold = value > 0.2 ? 128 : 0;

			const index = (x + y * width) * 4;

			const dx = x - width / 2;
			const dy = y - height / 2;
			const distance = Math.sqrt(dx * dx + dy * dy); // Euclidean distance

			// Normalize the distance to be between 0 and 1 (for a radial gradient effect)
			const maxDistance = Math.sqrt(
				((width / 2) * width) / 2 + ((height / 2) * height) / 2
			);

			const t = (distance / maxDistance) * 3.0 * Math.sin(dist);
			dist += 0.00001;

			const a = [0.5, 0.5, 0.5];
			const b = [0.5, 0.5, 0.5];
			const c = [1.0, 1.0, 1.0];
			const d = [0.0, 0.1, 0.2];

			const palette = getPalette(
				t,
				paletteSettings.a,
				paletteSettings.b,
				paletteSettings.c,
				paletteSettings.d
			);

			if (threshold == 0) {
				imageData.data[index] = palette[0] * 0.05; // Red
				imageData.data[index + 1] = palette[1] * 0.09; // Green
				imageData.data[index + 2] = palette[2] * 0.3; // Blue
				imageData.data[index + 3] = 255; // Alpha
			} else {
				imageData.data[index] = palette[0]; // Red
				imageData.data[index + 1] = palette[1]; // Green
				imageData.data[index + 2] = palette[2]; // Blue
				imageData.data[index + 3] = 255; // Alpha
			}
		}
	}

	ctx.putImageData(imageData, 0, 0);
	return canvas.toDataURL("image/jpeg");
}
