import { RippleSet, flushSync, track } from 'ripple';

describe('RippleSet', () => {
	it('handles add and delete operations', () => {
		function SetTest() {
			return <>
				let items = new RippleSet([1, 2, 3]);
				<button onClick={() => items.add(4)}>{'add'}</button>
				<button onClick={() => items.delete(2)}>{'delete'}</button>
				<Child {items} />
			</>;
		}

		function Child({ items }: { items: RippleSet<number> }) {
			return <>
				<pre>{JSON.stringify(items)}</pre>
				<pre>{items.size}</pre>
			</>;
		}

		render(SetTest);

		const addButton = container.querySelectorAll('button')[0];
		const deleteButton = container.querySelectorAll('button')[1];

		addButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('[1,2,3,4]');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('4');

		deleteButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('[1,3,4]');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('3');
	});

	it('handles clear operation', () => {
		function SetTest() {
			return <>
				let items = new RippleSet([1, 2, 3]);
				<button onClick={() => items.clear()}>{'clear'}</button>
				<Child {items} />
			</>;
		}

		function Child({ items }: { items: RippleSet<number> }) {
			return <>
				<pre>{JSON.stringify(items)}</pre>
				<pre>{items.size}</pre>
			</>;
		}

		render(SetTest);

		const clearButton = container.querySelector('button');

		clearButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('[]');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('0');
	});

	it('handles has operation', () => {
		function SetTest() {
			return <>
				let items = new RippleSet([1, 2, 3]);
				let &[hasValue] = track(() => items.has(2));
				<button onClick={() => items.delete(2)}>{'delete'}</button>
				<pre>{hasValue}</pre>
			</>;
		}

		render(SetTest);

		expect(container.querySelectorAll('pre')[0].textContent).toBe('true');

		const deleteButton = container.querySelectorAll('button')[0];

		deleteButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('false');
	});

	it('creates empty RippleSet using RippleSet() shorthand syntax', () => {
		function SetTest() {
			return <>
				let items = RippleSet();
				<button onClick={() => items.add(1)}>{'add'}</button>
				<pre>{items.size}</pre>
			</>;
		}

		render(SetTest);

		expect(container.querySelector('pre').textContent).toBe('0');

		const addButton = container.querySelector('button');
		addButton.click();
		flushSync();

		expect(container.querySelector('pre').textContent).toBe('1');
	});

	it('creates RippleSet with initial values using RippleSet() shorthand syntax', () => {
		function SetTest() {
			return <>
				let items = RippleSet([1, 2, 3, 4]);
				let &[hasValue] = track(() => items.has(3));
				<button onClick={() => items.delete(3)}>{'delete'}</button>
				<pre>{items.size}</pre>
				<pre>{hasValue}</pre>
			</>;
		}

		render(SetTest);

		expect(container.querySelectorAll('pre')[0].textContent).toBe('4');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('true');

		const deleteButton = container.querySelector('button');
		deleteButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('3');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('false');
	});

	it('handles all operations with RippleSet() shorthand syntax', () => {
		function SetTest() {
			return <>
				let items = RippleSet([10, 20, 30]);
				let &[values] = track(() => Array.from(items.values()));
				<button onClick={() => items.add(40)}>{'add'}</button>
				<button onClick={() => items.delete(20)}>{'delete'}</button>
				<button onClick={() => items.clear()}>{'clear'}</button>
				<pre>{JSON.stringify(values)}</pre>
				<pre>{items.size}</pre>
			</>;
		}

		render(SetTest);

		const [addButton, deleteButton, clearButton] = container.querySelectorAll('button');

		expect(container.querySelectorAll('pre')[0].textContent).toBe('[10,20,30]');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('3');

		addButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('[10,20,30,40]');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('4');

		deleteButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('[10,30,40]');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('3');

		clearButton.click();
		flushSync();

		expect(container.querySelectorAll('pre')[0].textContent).toBe('[]');
		expect(container.querySelectorAll('pre')[1].textContent).toBe('0');
	});
});
