import { openDB } from 'idb/with-async-ittr';
import { Cursor } from './Cursor.js';
import { IdbUrlHistory } from './idb/IdbUrlHistory.js';
import { IdbWsHistory } from './idb/IdbWsHistory.js';
import { IdbProjectUi } from './idb/IdbProjectUi.js';
/**
 * The implementation of the API Client app database in IDB.
 */
export class HttpClientIdbDatabase {
    constructor() {
        /**
         * The default limit of items returned by the list operation.
         * @default 35
         */
        this.defaultLimit = 35;
        this.cursor = new Cursor();
    }
    /**
     * The reference to the currently opened database.
     * This throws when the `initialize()` method wasn't called.
     */
    get db() {
        const db = this._db;
        if (!db) {
            throw new Error(`Attempted to access the database before opening a connection.`);
        }
        return db;
    }
    #urlHistory;
    /**
     * File metadata store.
     */
    get urlHistory() {
        const ref = this.#urlHistory;
        if (!ref) {
            throw new Error(`Store not initialized.`);
        }
        return ref;
    }
    #wsHistory;
    /**
     * File metadata store.
     */
    get wsHistory() {
        const ref = this.#wsHistory;
        if (!ref) {
            throw new Error(`Store not initialized.`);
        }
        return ref;
    }
    #projectUi;
    /**
     * File metadata store.
     */
    get projectUi() {
        const ref = this.#projectUi;
        if (!ref) {
            throw new Error(`Store not initialized.`);
        }
        return ref;
    }
    async initialize() {
        const db = await this.open();
        this.#urlHistory = new IdbUrlHistory(this, db);
        this.#wsHistory = new IdbWsHistory(this, db);
        this.#projectUi = new IdbProjectUi(this, db);
        await this.#urlHistory.warmup();
        await this.#wsHistory.warmup();
        await this.#projectUi.warmup();
    }
    async cleanup() {
        await this.urlHistory.cleanup();
        await this.wsHistory.cleanup();
        await this.projectUi.cleanup();
        this.db.close();
        this._db = undefined;
    }
    async readListState(source = {}) {
        if (source.cursor) {
            return this.cursor.decodeCursor(source.cursor);
        }
        return { ...source };
    }
    /**
     * Creates a database cursor when there are results.
     * This sets `skip` and `lastKey` parameters.
     *
     * @param state The last list state object
     * @param results The read results.
     * @returns A cursor to be used with pagination.
     */
    async createCursorIfNeeded(state, results) {
        if (!results.length) {
            return undefined;
        }
        const copy = { ...state };
        const { key } = results[results.length - 1];
        copy.skip = 1;
        copy.lastKey = key;
        return this.cursor.encodeCursor(copy);
    }
    /**
     * Opens the ARC store.
     * @returns The reference to the database
     */
    async open() {
        if (this._db) {
            return this._db;
        }
        const dbResult = await openDB('HttpClient', 1, {
            upgrade: (db) => {
                const stores = [
                    'UrlHistory', 'WsHistory', 'ProjectUi',
                ];
                const names = db.objectStoreNames;
                for (const name of stores) {
                    const exists = names.contains(name);
                    const fnName = `_${name}UpgradeHandler`;
                    if (typeof this[fnName] === 'function') {
                        this[fnName](db, exists);
                    }
                    else if (!exists) {
                        this._defaultUpgradeHandler(name, db, exists);
                    }
                }
            },
        });
        this._db = dbResult;
        return dbResult;
    }
    /**
     * Creates a default store where the stored object is identified by the `data.key` path.
     * @param name The store name to create
     * @param db The handler to the database
     */
    _defaultUpgradeHandler(name, db, storeExists) {
        if (storeExists) {
            return;
        }
        db.createObjectStore(name, { keyPath: 'data.key' });
    }
    _UrlHistoryUpgradeHandler(db, storeExists) {
        if (storeExists) {
            return;
        }
        db.createObjectStore('UrlHistory', { keyPath: 'key' });
    }
    _WsHistoryUpgradeHandler(db, storeExists) {
        if (storeExists) {
            return;
        }
        db.createObjectStore('WsHistory', { keyPath: 'key' });
    }
    _ProjectUiUpgradeHandler(db, storeExists) {
        if (storeExists) {
            return;
        }
        const store = db.createObjectStore('ProjectUi', { keyPath: ['meta.project', 'meta.key'] });
        const typed = store;
        typed.createIndex('project', 'meta.project', { unique: false });
    }
}
//# sourceMappingURL=HttpClientIdbDatabase.js.map