var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var MintblueReader_1;
import { Mintblue } from '../mintblue.js';
import { LogClass } from './utils.js';
/**
 * Implementation of the Reader interface for the Mintblue SDK.
 * This class facilitates listening to transaction events using Mintblue and dispatching them accordingly.
 *
 * @category Machine
 */
let MintblueReader = MintblueReader_1 = class MintblueReader {
    actionDispatcher;
    mintblue;
    project_id;
    connectionHandle;
    /**
     * Factory method to create an instance of the MintblueReader.
     * @param sdkToken - The token for the Mintblue SDK.
     * @param project_id - The ID of the project to listen to.
     * @returns An instance of MintblueReader.
     */
    static async create(sdkToken, project_id) {
        const mintblue = await Mintblue.create({ token: sdkToken });
        return new MintblueReader_1(mintblue, project_id);
    }
    /**
     * Constructs a MintblueReader.
     * @param mintblue - The Mintblue instance.
     * @param project_id - The ID of the project to listen to.
     */
    constructor(mintblue, project_id) {
        this.project_id = project_id;
        this.mintblue = mintblue;
        this.connectionHandle = null;
    }
    /**
     * Initializes the action dispatcher.
     * @param actionDispatcher - The function to dispatch actions.
     */
    initialize(actionDispatcher) {
        this.actionDispatcher = actionDispatcher;
    }
    /**
     * Starts the reader to begin listening for Mintblue project events.
     */
    async start(lastActionId) {
        if (!this.mintblue) {
            throw new Error('mintBlue SDK not initialized yet');
        }
        this.connectionHandle = await this.mintblue.experimentalStreamProject({
            project_id: this.project_id,
            history: true,
            ...(lastActionId ? { last_event_id: lastActionId } : {}),
            onError(e) {
                console.log('Mintblue driver error: ', e);
            },
            onTransaction: async (tx) => {
                const action = await this.parseTransactionIntoAction(tx);
                if (action) {
                    action.id = tx.txid;
                    await this.actionDispatcher(action, { project_id: this.project_id, tx }, false); // TODO isResynchronizing
                }
            },
        });
    }
    /**
     * Parses a Mintblue transaction into a standardized action.
     * @param tx - The Mintblue transaction.
     * @returns An action or null if parsing is unsuccessful.
     */
    async parseTransactionIntoAction(tx) {
        if (!this.mintblue) {
            throw new Error('mintBlue SDK not initialized yet');
        }
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        const [output, _] = await this.mintblue.parseTransaction(tx.txid, tx.rawtx);
        if (output.type === 'data' && typeof output.value === 'object') {
            if (output.value.f && output.value.args) {
                const action = {
                    id: tx.txid,
                    ...output.value,
                };
                return action;
            }
        }
        else if (output.type === 'data' && typeof output.value === 'string') {
            const action = {
                id: tx.txid,
                ...JSON.parse(output.value),
            };
            return action;
        }
        return null;
    }
    /**
     * Stops the reader from listening to events. (Implementation may be added in the future)
     */
    stop() {
        if (this.connectionHandle && this.connectionHandle.close) {
            this.connectionHandle.close();
        }
        //
    }
    async fetch(lastActionId) {
        if (lastActionId) {
            const txs = await this.mintblue.transactionsAfterTxid({ project_id: this.project_id, txid: lastActionId });
            for (const tx of txs) {
                const action = await this.parseTransactionIntoAction(tx);
                if (action) {
                    action.id = tx.txid;
                    await this.actionDispatcher(action, { project_id: this.project_id, tx }, false); // TODO isResynchronizing
                }
            }
            return;
        }
        const txs = await this.mintblue.queryTransactions({
            where: {
                project_id: this.project_id,
            },
            sort: 'created_at',
            order: 'asc',
            rawtx: true,
        });
        for (const tx of txs) {
            const action = await this.parseTransactionIntoAction(tx);
            if (action) {
                action.id = tx.txid;
                await this.actionDispatcher(action, { project_id: this.project_id, tx }, false); // TODO isResynchronizing
            }
        }
    }
};
MintblueReader = MintblueReader_1 = __decorate([
    LogClass()
], MintblueReader);
export { MintblueReader };
//# sourceMappingURL=MintblueReader.js.map