import { Component, createEffect, createSignal, on } from 'solid-js';

import styles from './Page.module.css';
import Navigation from '../Navigation';
import { createRandomGenerator } from '../random';

const SYMBOLS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _#+';

const StrNoise: Component = () => {
	const [output, setOutput] = createSignal('');
	const [input, setInput] = createSignal('');
	const [noiseLevel, setNoiseLevel] = createSignal(10);
	const [seed, setSeed] = createSignal('0');

	const [shuffle, setShuffle] = createSignal(true);
	const [randomize, setRandomize] = createSignal(true);
	const [swapAdjacent, setSwapAdjancent] = createSignal(false);

	createEffect(on([input, noiseLevel, seed, shuffle, randomize, swapAdjacent], () => {
		const generator = createRandomGenerator(seed());

		const types = [];
		if (shuffle()) types.push('shuffle');
		if (randomize()) types.push('randomize');
		if (swapAdjacent()) types.push('swap_adjacent');

		const arr = input().split('');
		const its = noiseLevel() / 100 * arr.length * 2;
		for (let i = 0; i < its; i++) {
			const type = types[Math.floor(generator() * types.length)];

			if (type == 'shuffle') {
				const a = Math.floor(generator() * arr.length);
				const b = Math.floor(generator() * arr.length);
				[arr[a], arr[b]] = [arr[b], arr[a]];
			} else if (type == 'randomize') {
				const i = Math.floor(generator() * arr.length);
				arr[i] = SYMBOLS[Math.floor(generator() * SYMBOLS.length)];
			} else if (type == 'swap_adjacent') {
				const a = Math.floor(generator() * (arr.length - 1));
				[arr[a], arr[a + 1]] = [arr[a + 1], arr[a]];
			}
		}
		setOutput(arr.join(''));
	}));

	let outputField: HTMLInputElement | undefined;

	const copy = async () => {
		outputField!.select();
		document.execCommand('copy');
	};

	return (
		<div class={styles.page}>
			<h1>String Noise</h1>
			<h2>Input</h2>
			<textarea value={input()} oninput={e => setInput(e.currentTarget.value)} />
			<h3>Noise Level</h3>
			<input type={'range'} min={0} max={100} value={noiseLevel()} oninput={e => setNoiseLevel(parseInt(e.currentTarget.value))} />
			<h3>Noise Types</h3>
			<div class={styles.checkbox}>
				<input type={'checkbox'} checked={shuffle()} onchange={e => setShuffle(e.currentTarget.checked)} />
				<label>Shuffle</label>
			</div>
			<div class={styles.checkbox}>
				<input type={'checkbox'} checked={randomize()} onchange={e => setRandomize(e.currentTarget.checked)} />
				<label>Randomize</label>
			</div>
			<div class={styles.checkbox}>
				<input type={'checkbox'} checked={swapAdjacent()} onchange={e => setSwapAdjancent(e.currentTarget.checked)} />
				<label>Swap Adjacent</label>
			</div>
			<h3>Seed</h3>
			<input min={0} max={100} value={seed()} onInput={e => setSeed(e.currentTarget.value)} />
			<h2>Output</h2>
			<input value={output()} ref={outputField} />
			<button onclick={copy}>Copy Output</button>
			<h2>All Tools</h2>
			<Navigation />
		</div>
	);
};

export default StrNoise;