/**
 * IndexDBFileSystemStorageAdapter implements LocalStorageAdapter using IndexedDB.
 * Suitable for web browsers and web-based environments.
 */
export class IndexDBFileSystemStorageAdapter {
    databaseName;
    dbPromise;
    constructor(databaseName = 'PowerSyncFiles') {
        this.databaseName = databaseName;
    }
    async initialize() {
        this.dbPromise = new Promise((resolve, reject) => {
            const request = indexedDB.open(this.databaseName, 1);
            request.onupgradeneeded = () => {
                request.result.createObjectStore('files');
            };
            request.onsuccess = () => resolve(request.result);
            request.onerror = () => reject(request.error);
        });
    }
    async clear() {
        const db = await this.dbPromise;
        return new Promise((resolve, reject) => {
            const tx = db.transaction('files', 'readwrite');
            const store = tx.objectStore('files');
            const req = store.clear();
            req.onsuccess = () => resolve();
            req.onerror = () => reject(req.error);
        });
    }
    getLocalUri(filename) {
        return `indexeddb://${this.databaseName}/files/${filename}`;
    }
    async getStore(mode = 'readonly') {
        const db = await this.dbPromise;
        const tx = db.transaction('files', mode);
        return tx.objectStore('files');
    }
    async saveFile(filePath, data) {
        const store = await this.getStore('readwrite');
        let dataToStore;
        let size;
        if (typeof data === 'string') {
            const binaryString = atob(data);
            const bytes = new Uint8Array(binaryString.length);
            for (let i = 0; i < binaryString.length; i++) {
                bytes[i] = binaryString.charCodeAt(i);
            }
            dataToStore = bytes.buffer;
            size = bytes.byteLength;
        }
        else {
            dataToStore = data;
            size = dataToStore.byteLength;
        }
        return await new Promise((resolve, reject) => {
            const req = store.put(dataToStore, filePath);
            req.onsuccess = () => resolve(size);
            req.onerror = () => reject(req.error);
        });
    }
    async readFile(fileUri, options) {
        const store = await this.getStore();
        return new Promise((resolve, reject) => {
            const req = store.get(fileUri);
            req.onsuccess = async () => {
                if (!req.result) {
                    reject(new Error('File not found'));
                    return;
                }
                resolve(req.result);
            };
            req.onerror = () => reject(req.error);
        });
    }
    async deleteFile(uri, options) {
        const store = await this.getStore('readwrite');
        await new Promise((resolve, reject) => {
            const req = store.delete(uri);
            req.onsuccess = () => resolve();
            req.onerror = () => reject(req.error);
        });
    }
    async fileExists(fileUri) {
        const store = await this.getStore();
        return new Promise((resolve, reject) => {
            const req = store.get(fileUri);
            req.onsuccess = () => resolve(!!req.result);
            req.onerror = () => reject(req.error);
        });
    }
    async makeDir(path) {
        // No-op for IndexedDB as it does not have a directory structure
    }
    async rmDir(path) {
        const store = await this.getStore('readwrite');
        const range = IDBKeyRange.bound(path + '/', path + '/\uffff', false, false);
        await new Promise((resolve, reject) => {
            const req = store.delete(range);
            req.onsuccess = () => resolve();
            req.onerror = () => reject(req.error);
        });
    }
}
