import { Model } from '../core/Model.js';
import { exponentialBackoffDelay, shouldRetryApiError, retry } from './retry_logic.js';
import { fromError } from '../exceptions/builder.js';
import services from '../services/api_service.js';
import { LiveData } from '../reactive/LiveData.js';
export var ModelState;
(function (ModelState) {
    /**
     * Not doing anything.
     */
    ModelState[ModelState["idle"] = 0] = "idle";
    /**
     * Currently querying for file data.
     */
    ModelState[ModelState["reading"] = 1] = "reading";
    /**
     * Data was received and the result yielded no results or less than the limit.
     */
    ModelState[ModelState["ended"] = 2] = "ended";
})(ModelState || (ModelState = {}));
export class DataCatalogModel extends Model {
    /**
     * The current state of the model.
     */
    state = ModelState.idle;
    /**
     * The pagination cursor for files to use with the next query.
     */
    cursor;
    /**
     * Optional organization ID to filter the data catalog by.
     */
    oid;
    /**
     * The SDK service instance.
     */
    sdk;
    /**
     * When set, the model will only return files that match this query.
     */
    #query;
    get query() {
        return this.#query;
    }
    set query(value) {
        if (this.#query === value) {
            return;
        }
        this.#query = value;
        this.resetPageState();
    }
    #scope = 'public';
    get scope() {
        return this.#scope;
    }
    set scope(value) {
        if (this.#scope === value) {
            return;
        }
        this.#scope = value;
        this.resetPageState();
    }
    #sort;
    get sort() {
        return this.#sort;
    }
    set sort(value) {
        if (this.#sort === value) {
            return;
        }
        this.#sort = value;
        this.resetPageState();
    }
    #lifecycle = 'stable';
    get lifecycle() {
        return this.#lifecycle;
    }
    set lifecycle(value) {
        if (this.#lifecycle === value) {
            return;
        }
        this.#lifecycle = value;
        this.resetPageState();
    }
    get value() {
        return this.raw;
    }
    constructor(sdk, oid) {
        super();
        this.oid = oid;
        this.sdk = sdk;
        this.raw = new LiveData([]);
    }
    resetPageState() {
        this.cursor = undefined;
        this.state = ModelState.idle;
        this.value.set([]);
    }
    async scheduleQuery() {
        this.debounce(this.#runQuery);
        await this.taskComplete;
    }
    async #runQuery() {
        if (this.state !== ModelState.idle) {
            return;
        }
        this.state = ModelState.reading;
        try {
            const result = await this.#listFiles();
            this.#processResults(result);
        }
        catch (e) {
            const err = fromError(e);
            this.notifyError(err);
            this.state = ModelState.idle;
        }
        this.dispatchEvent(new Event('querycomplete'));
    }
    async #listFiles() {
        const sdk = await services.get('sdk');
        const operation = async () => {
            const opts = this.getPageQueryOptions();
            return sdk.dataCatalog.list(opts);
        };
        const retryOptions = {
            retries: this.retryCount,
            delayMs: exponentialBackoffDelay,
            shouldRetry: shouldRetryApiError,
        };
        return retry(operation, retryOptions);
    }
    getPageQueryOptions() {
        const result = {
            cursor: this.cursor,
            limit: this.limit,
            oid: this.oid,
            scope: this.scope,
        };
        if (this.sort) {
            result.sort = this.sort;
        }
        const { lifecycle, query } = this;
        const filters = [];
        if (query) {
            filters.push({ field: 'name', value: query, operator: 'con' });
        }
        if (lifecycle) {
            filters.push({ field: 'lifecycle', value: lifecycle, operator: 'eq' });
        }
        if (filters.length === 1) {
            result.filter = filters[0];
        }
        else if (filters.length > 1) {
            result.filter = {
                op: 'AND',
                filters,
            };
        }
        return result;
    }
    #processResults(result) {
        const { items, cursor } = result;
        if (cursor) {
            this.cursor = cursor;
        }
        if (!items.length) {
            this.state = ModelState.ended;
            return;
        }
        this.value.set(this.value.value.concat(items));
        this.state = ModelState.idle;
    }
}
//# sourceMappingURL=DataCatalogModel.js.map