const DB_VERSION = 1;

const ASSET_DB_NAME = 'GLTFStorage';
const ASSET_STORE_NAME = 'models';

const IMAGE_DB_NAME = 'ImageStorage';
const IMAGE_STORE_NAME = 'images';

export function initializeAssetDB(): Promise<IDBDatabase> {
	return new Promise((resolve, reject) => {
		const request = indexedDB.open(ASSET_DB_NAME, DB_VERSION);

		request.onupgradeneeded = () => {
			const db = request.result;
			if (!db.objectStoreNames.contains(ASSET_STORE_NAME)) {
				db.createObjectStore(ASSET_STORE_NAME);
			}
		};

		request.onsuccess = () => resolve(request.result);
		request.onerror = () => reject(request.error);
	});
}

export async function storeGLTF(key: string, file: Blob): Promise<void> {
	const db = await initializeAssetDB();

	return new Promise((resolve, reject) => {
		const transaction = db.transaction(ASSET_STORE_NAME, 'readwrite');
		const store = transaction.objectStore(ASSET_STORE_NAME);
		const request = store.put(file, key);

		request.onsuccess = () => resolve();
		request.onerror = () => reject(request.error);
	});
}

export async function retrieveGLTF(key: string): Promise<Blob | undefined> {
	const db = await initializeAssetDB();

	return new Promise((resolve, reject) => {
		const transaction = db.transaction(ASSET_STORE_NAME, 'readonly');
		const store = transaction.objectStore(ASSET_STORE_NAME);
		const request = store.get(key);

		request.onsuccess = () => resolve(request.result as Blob | undefined);
		request.onerror = () => reject(request.error);
	});
}

export function initializeImageDB(): Promise<IDBDatabase> {
	return new Promise((resolve, reject) => {
		const request = indexedDB.open(IMAGE_DB_NAME, DB_VERSION);

		request.onupgradeneeded = () => {
			const db = request.result;
			if (!db.objectStoreNames.contains(IMAGE_STORE_NAME)) {
				db.createObjectStore(IMAGE_STORE_NAME);
			}
		};

		request.onsuccess = () => resolve(request.result);
		request.onerror = () => reject(request.error);
	});
}

export async function storeImage(key: string, file: Blob): Promise<void> {
	const db = await initializeImageDB();

	return new Promise((resolve, reject) => {
		const transaction = db.transaction(IMAGE_STORE_NAME, 'readwrite');
		const store = transaction.objectStore(IMAGE_STORE_NAME);
		const request = store.put(file, key);

		request.onsuccess = () => resolve();
		request.onerror = () => reject(request.error);
	});
}

export async function retrieveImage(key: string): Promise<Blob | undefined> {
	const db = await initializeImageDB();

	return new Promise((resolve, reject) => {
		const transaction = db.transaction(IMAGE_STORE_NAME, 'readonly');
		const store = transaction.objectStore(IMAGE_STORE_NAME);
		const request = store.get(key);

		request.onsuccess = () => resolve(request.result as Blob | undefined);
		request.onerror = () => reject(request.error);
	});
}