<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
</head>
<body>
	<script type="module">
		function reqAsPromise(req) {
			return new Promise((resolve, reject) => {
				req.addEventListener("success", event => resolve(event.target.result));
				req.addEventListener("error", event => reject(event.target.error));
			});
		}

		function txnAsPromise(txn) {
			return new Promise((resolve, reject) => {
				txn.addEventListener("complete", resolve);
				txn.addEventListener("abort", reject);
			});
		}

		function readAll(cursor) {
			return new Promise((resolve, reject) => {
				const results = [];
				cursor.onerror = (event) => {
					reject(new Error("Query failed: " + event.target.errorCode));
				};
				cursor.onsuccess = (event) => {
					const cursor = event.target.result;
					if (!cursor) {
						resolve(results);
					} else {
						results.push(cursor.value);
						cursor.continue();
					}
				};
			});
		}

		let seed = 13423;
		function prn() {
			let x = Math.sin(seed++) * 10000;
			return x - Math.floor(x);
		}

		function pad(str, len) {
			return str + " ".repeat(len - str.length);
		}

		function formatByteArray(a) {
			return `[${Array.from(a).join(",")}]`;
		}

		async function main() {
			let isNew = false;
			const openReq = window.indexedDB.open("bin_key_sorting_test", 1);
			openReq.onupgradeneeded = (ev) => {
				const db = ev.target.result;
				db.createObjectStore("test", {keyPath: ["binKey"]});
				isNew = true;
			};
			const db = await reqAsPromise(openReq);
			// fill test store with some data
			if (isNew) {
				const txn = db.transaction("test", "readwrite");
				const store = txn.objectStore("test");
				const rndByte = () => Math.ceil(prn() * 255);
				for(let i = 0; i < 10; ++i) {
					const b1 = rndByte(), b2 = rndByte(), b3 = rndByte(), b4 = rndByte();
					console.log(`adding key (${b1},${b2},${b3},${b4})`);
					store.add({binKey: new Uint8Array([b1, b2, b3, b4])});
				}
				store.add({binKey: new Uint8Array([0x80, 0x00, 0x00, 0x00])});
				store.add({binKey: new Uint8Array([0x00, 0x00, 0x00, 0x00])});
				store.add({binKey: new Uint8Array([0x7F, 0xFF, 0xFF, 0xFF])});
				store.add({binKey: new Uint8Array([0xFF, 0xFF, 0xFF, 0xFF])});
				await txnAsPromise(txn);
			}
			
			const txn = db.transaction("test", "readonly");
			const store = txn.objectStore("test");
			const range = IDBKeyRange.upperBound(
				// Uint8Array.from([0x00, 0x00, 0x00, 0x00]).buffer,
				Uint8Array.from([0xFF, 0xFF, 0xFF, 0xFF]).buffer,
				// new Uint8Array([0x80, 0x00, 0x00, 0x00]).buffer, new
				// Uint8Array([0x7F, 0xFF, 0xFF, 0xFF]).buffer,
				false
			);
			// const values = await readAll(store.openCursor(range, "next"));
			const values = await readAll(store.openCursor(range, "prev"));

			console.log(pad(`[uint8;4]`, 20) + " [int8;4]");
			for (const v of values) {
				const uintStr = formatByteArray(new Uint8Array(v.binKey));
				const intStr = formatByteArray(new Int8Array(v.binKey));
				console.log(pad(uintStr, 20) + " " + intStr);
			}
		}

		main();
	</script>
</body>
</html>