
const { persistentSubscriptionToAllSettingsFromDefaults, ROUND_ROBIN, START, FORWARDS, BACKWARDS, END } = require("@eventstore/db-client");
const ProjectionClient = require("./client/projectionClient").ProjectionClient;
const StreamClient = require("./client/streamClient").StreamClient;

class readModel {

    constructor() {
        this.esClient = new StreamClient('u', 'p', 'url');
        this.projectionClient = new ProjectionClient();
    }

    /**
     * create a projection
     */
    async createProjection(projectionName, projectionQuery) {
        return await this.projectionClient.create(projectionName, projectionQuery);
    }

    /**
     * update a projection
     */
    async updateProjection(projectionName, projectionQuery) {
        return await this.projectionClient.update(projectionName, projectionQuery);
    }

    /**
     * enable the projection
     * @param {*} projectionName 
     * @returns 
     */
    enableProjection(projectionName) {
        return this.projectionClient.enable(projectionName);
    }

    /**
     * disable the projection
     */
    disableProjection(pNameOrType) {
        return this.projectionClient.disable(pNameOrType);
    }

    /**
     * delete a projection
     * 
     * @param {*} projectionName 
     * @returns 
     */
    async deleteProjection(projectionName) {
        return await this.projectionClient.delete(projectionName);
    }

    /**
     * abort a projection
     * 
     * @param {*} projectionName 
     * @returns 
     */
    async abortProjection(projectionName) {
        return await this.projectionClient.delete(projectionName);
    }

    /**
     * read events from a stream 
     * */
    async readStream(streamName, options) {
        return await this.esClient.readStream(streamName, options);
    }

    /*
    * read events from $all stream
    * */
    async readAllStream(options) {
        return await this.esClient.readAllStream(options);
    }

    /*
    * read projection status
    * */
    async getStatus(name) {
        return await this.projectionClient.getStatus(name);
    }

    /**
    * read projection state
     */
    async resState(name) {
        return await this.projectionClient.getState(name);
    }

    /**
     * read projection result
     */
    async getResult(name) {
        return await this.projectionClient.getResult(name);
    }

    /**
     * 
     * list all projections
     */
    async listProjections() {
        return await this.projectionClient.getList();
    }

    /**
    * subscribe event from a stream
    * {
    *   fromRevision: START | END | Bigint
    *   resolveLinkTos: true
    * }
     */
    async subscribe(streamName, fromRevision = END) {
        return await this.esClient.subscribe(streamName, { fromRevision });
    }

    /**
     * subscribe event from $all stream
     * {
     *  fromPosition: {
     *      commit: BigInt(1056),
     *      prepare: BingInt(1056)
     *  }
     * }
     * live stream 
     * {
     *      fromPosition: END
     * }
     * filter stream
     * {
     *      filter: 
     *          streamNameFilter({
     *              prefix: ["test-", "other-"]
     *          })
     *      filter: 
     *           excludeSystemEvents()
     * }
     *  
     */
    async subscribeAll(fromPosition, filter = {}, credentials = {}) {
        return await this.esClient.subscribeAll({ fromPosition, filter, credentials });
    }

    async subscribeAllStream(fromPosition, filter = {}, credentials = {}) {
        return await this.esClient.subscribeAllStream({ fromPosition, filter, credentials });
    }

    /**
    * subscribe subscription group from o sgroup
    * 13.list continuous projections
     */
    subscribeGroup(streamName, groupName, nakAction) {
        return this.esClient.subscribeGroup(streamName, groupName, nakAction);
    }

    /**
     * connecting to a subscribe group
     * bufferSize: RoundRobin | DispatchToSingle | Pinned
     * 
     * @param {*} streamName 
     * @param {*} groupName 
     * @returns 
     */
    subscribeToPersistentSubscriptionToStream(streamName, groupName) {
        return this.esClient.subscribeToPersistentSubscriptionToStream(
            streamName,
            groupName,
            persistentSubscriptionToAllSettingsFromDefaults({
                bufferSize: ROUND_ROBIN
            })
        );
    }

    /**
     * connecting to a subscribe group
     * 
     * @param {*} streamName 
     * @param {*} groupName 
     * @returns 
     */
    createPersistentSubscriptionToStream(streamName, groupName) {
        return this.esClient.createPersistentSubscriptionToStream(streamName, groupName);
    }

    /**
     * update subscription 
     * 
     * @param {*} streamName 
     * @param {*} groupName 
     */
    updatePersistentSubscriptionToStream(streamName, groupName) {
        return this.esClient.updateSubscriptionGroup(
            streamName,
            groupName,
            persistentSubscriptionToAllSettingsFromDefaults({
                resolveLinkTos: true,
                checkPointLowerBound: 20
            })
        );
    }

    /**
     * delete subscription group
     * 
     * @param {*} streamName 
     * @param {*} groupName 
     * @returns 
     */
    async deleteSubscriptionGroup(streamName, groupName) {
        return await this.esClient.deleteSubscriptionGroup(streamName, groupName);
    }
}

exports.readModel = readModel;
