"use strict";
/* --------------------------------------------------------------------------------------------
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 * ------------------------------------------------------------------------------------------ */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProgressPart = void 0;
const vscode_1 = require("vscode");
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
const Is = require("./utils/is");
class ProgressPart {
    constructor(_client, _token, done) {
        this._client = _client;
        this._token = _token;
        this._reported = 0;
        this._infinite = false;
        this._lspProgressDisposable = this._client.onProgress(vscode_languageserver_protocol_1.WorkDoneProgress.type, this._token, (value) => {
            switch (value.kind) {
                case 'begin':
                    this.begin(value);
                    break;
                case 'report':
                    this.report(value);
                    break;
                case 'end':
                    this.done();
                    done && done(this);
                    break;
            }
        });
    }
    begin(params) {
        this._infinite = params.percentage === undefined;
        // the progress as already been marked as done / canceled. Ignore begin call
        if (this._lspProgressDisposable === undefined) {
            return;
        }
        // Since we don't use commands this will be a silent window progress with a hidden notification.
        void vscode_1.window.withProgress({ location: vscode_1.ProgressLocation.Window, cancellable: params.cancellable, title: params.title }, async (progress, cancellationToken) => {
            // the progress as already been marked as done / canceled. Ignore begin call
            if (this._lspProgressDisposable === undefined) {
                return;
            }
            this._progress = progress;
            this._cancellationToken = cancellationToken;
            this._tokenDisposable = this._cancellationToken.onCancellationRequested(() => {
                this._client.sendNotification(vscode_languageserver_protocol_1.WorkDoneProgressCancelNotification.type, { token: this._token });
            });
            this.report(params);
            return new Promise((resolve, reject) => {
                this._resolve = resolve;
                this._reject = reject;
            });
        });
    }
    report(params) {
        if (this._infinite && Is.string(params.message)) {
            this._progress !== undefined && this._progress.report({ message: params.message });
        }
        else if (Is.number(params.percentage)) {
            const percentage = Math.max(0, Math.min(params.percentage, 100));
            const delta = Math.max(0, percentage - this._reported);
            this._reported += delta;
            this._progress !== undefined && this._progress.report({ message: params.message, increment: delta });
        }
    }
    cancel() {
        this.cleanup();
        if (this._reject !== undefined) {
            this._reject();
            this._resolve = undefined;
            this._reject = undefined;
        }
    }
    done() {
        this.cleanup();
        if (this._resolve !== undefined) {
            this._resolve();
            this._resolve = undefined;
            this._reject = undefined;
        }
    }
    cleanup() {
        if (this._lspProgressDisposable !== undefined) {
            this._lspProgressDisposable.dispose();
            this._lspProgressDisposable = undefined;
        }
        if (this._tokenDisposable !== undefined) {
            this._tokenDisposable.dispose();
            this._tokenDisposable = undefined;
        }
        this._progress = undefined;
        this._cancellationToken = undefined;
    }
}
exports.ProgressPart = ProgressPart;
