export class SharedWASQLiteConnection {
    options;
    isClosing;
    // Keeps track if this current hold if the shared connection has a hold
    activeHoldId;
    constructor(options) {
        this.options = options;
        // Add this client ID to the set of known clients
        this.clientIds.add(options.clientId);
        this.isClosing = false;
        this.activeHoldId = null;
    }
    get logger() {
        return this.options.logger;
    }
    get dbEntry() {
        return this.options.dbMap.get(this.options.dbFilename);
    }
    get connection() {
        return this.dbEntry.db;
    }
    get clientIds() {
        return this.dbEntry.clientIds;
    }
    async init() {
        // No-op since the connection is already initialized when it was created
    }
    async markHold() {
        this.activeHoldId = await this.connection.markHold();
        return this.activeHoldId;
    }
    async releaseHold(id) {
        try {
            await this.connection.releaseHold(id);
        }
        finally {
            this.activeHoldId = null;
        }
    }
    async isAutoCommit() {
        return this.connection.isAutoCommit();
    }
    /**
     * Handles closing of a shared connection.
     * The connection is only closed if there are no active clients using it.
     */
    async close() {
        // This prevents further statements on this connection from being executed
        this.isClosing = true;
        const { clientIds, logger } = this;
        const { clientId, dbFilename, dbMap } = this.options;
        logger.debug(`Close requested from client ${clientId} of ${[...clientIds]}`);
        clientIds.delete(clientId);
        if (this.activeHoldId) {
            // We can't cleanup here since we're not in a lock context.
            // The cleanup will occur once a new hold is acquired.
            this.logger.info(`Hold ${this.activeHoldId} was still active when the connection was closed. Cleanup will occur once a new hold is acquired.`);
        }
        if (clientIds.size == 0) {
            logger.debug(`Closing connection to ${this.options}.`);
            const connection = this.connection;
            dbMap.delete(dbFilename);
            await connection.close();
            return;
        }
        logger.debug(`Connection to ${dbFilename} not closed yet due to active clients.`);
        return;
    }
    async withClosing(action) {
        if (this.isClosing) {
            throw new Error('Connection is closing');
        }
        return action();
    }
    async execute(sql, params) {
        return this.withClosing(() => this.connection.execute(sql, params));
    }
    async executeRaw(sql, params) {
        return this.withClosing(() => this.connection.executeRaw(sql, params));
    }
    executeBatch(sql, params) {
        return this.withClosing(() => this.connection.executeBatch(sql, params));
    }
    registerOnTableChange(callback) {
        return this.connection.registerOnTableChange(callback);
    }
    getConfig() {
        return this.connection.getConfig();
    }
}
