/*!
 * Copyright (C) Microsoft Corporation. All rights reserved.
 */
// SYNC: this file is duplicated in packages/managed-apps-cli/src/Utils/Spinner.ts.
// Changes here must be mirrored there until a shared CLI utilities package exists.
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
export class CliSpinner {
    _timer = null;
    _frameIndex = 0;
    // Arrow functions so `this` is stable when passed to process.on/off.
    _restoreCursor = () => {
        process.stdout.write('\r\x1B[K'); // erase spinner line
        process.stdout.write('\x1B[?25h'); // show cursor
    };
    _handleSIGINT = () => {
        if (this._timer !== null)
            clearInterval(this._timer);
        this._restoreCursor();
        // Re-raise so the process actually exits with the correct signal.
        process.kill(process.pid, 'SIGINT');
    };
    _handleSIGTERM = () => {
        if (this._timer !== null)
            clearInterval(this._timer);
        this._restoreCursor();
        process.kill(process.pid, 'SIGTERM');
    };
    _handleUncaughtException = (error) => {
        if (this._timer !== null)
            clearInterval(this._timer);
        this._restoreCursor();
        // Re-throw so Node.js prints the error and exits with code 1.
        throw error;
    };
    _handleUnhandledRejection = (reason) => {
        if (this._timer !== null)
            clearInterval(this._timer);
        this._restoreCursor();
        throw reason;
    };
    start() {
        if (this._timer !== null)
            return;
        process.stdout.write('\x1B[?25l'); // hide cursor
        // Restore cursor if the process exits before stop() is called normally.
        process.once('exit', this._restoreCursor);
        process.once('SIGINT', this._handleSIGINT);
        process.once('SIGTERM', this._handleSIGTERM);
        process.once('uncaughtException', this._handleUncaughtException);
        process.once('unhandledRejection', this._handleUnhandledRejection);
        this._timer = setInterval(() => {
            process.stdout.write(`\r${SPINNER_FRAMES[this._frameIndex]}`);
            this._frameIndex = (this._frameIndex + 1) % SPINNER_FRAMES.length;
        }, 80);
    }
    stop() {
        if (this._timer !== null) {
            clearInterval(this._timer);
            this._timer = null;
            this._frameIndex = 0;
            // Clean up exit handlers registered in start().
            process.off('exit', this._restoreCursor);
            process.off('SIGINT', this._handleSIGINT);
            process.off('SIGTERM', this._handleSIGTERM);
            process.off('uncaughtException', this._handleUncaughtException);
            process.off('unhandledRejection', this._handleUnhandledRejection);
            this._restoreCursor();
        }
    }
}
//# sourceMappingURL=Spinner.js.map