"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const cli_cursor_1 = tslib_1.__importDefault(require("cli-cursor"));
const readline = tslib_1.__importStar(require("readline"));
const isLegacyConsole = process.platform === "win32" &&
    !(process.env.TERM_PROGRAM === "vscode" || !!process.env.WT_SESSION);
const ansiRegex = /(\u009B|\u001B\[)[0-?]*[ -\/]*[@-~]/g;
const SpinnerFastInterval = 10;
const SpinnerSlowInterval = 50;
const SpinnerFrames = [
    "⢀⠀",
    "⡀⠀",
    "⠄⠀",
    "⢂⠀",
    "⡂⠀",
    "⠅⠀",
    "⢃⠀",
    "⡃⠀",
    "⠍⠀",
    "⢋⠀",
    "⡋⠀",
    "⠍⠁",
    "⢋⠁",
    "⡋⠁",
    "⠍⠉",
    "⠋⠉",
    "⠋⠉",
    "⠉⠙",
    "⠉⠙",
    "⠉⠩",
    "⠈⢙",
    "⠈⡙",
    "⢈⠩",
    "⡀⢙",
    "⠄⡙",
    "⢂⠩",
    "⡂⢘",
    "⠅⡘",
    "⢃⠨",
    "⡃⢐",
    "⠍⡐",
    "⢋⠠",
    "⡋⢀",
    "⠍⡁",
    "⢋⠁",
    "⡋⠁",
    "⠍⠉",
    "⠋⠉",
    "⠋⠉",
    "⠉⠙",
    "⠉⠙",
    "⠉⠩",
    "⠈⢙",
    "⠈⡙",
    "⠈⠩",
    "⠀⢙",
    "⠀⡙",
    "⠀⠩",
    "⠀⢘",
    "⠀⡘",
    "⠀⠨",
    "⠀⢐",
    "⠀⡐",
    "⠀⠠",
    "⠀⢀",
    "⠀⡀",
];
const spinnerFramesCP437 = ["-", "\\", "|", "/"];
var SpinnerState;
(function (SpinnerState) {
    SpinnerState[SpinnerState["Stopped"] = 0] = "Stopped";
    SpinnerState[SpinnerState["Starting"] = 1] = "Starting";
    SpinnerState[SpinnerState["Running"] = 2] = "Running";
    SpinnerState[SpinnerState["Paused"] = 3] = "Paused";
})(SpinnerState || (SpinnerState = {}));
class Spinner {
    constructor() {
        this.textSource = null;
        this.lastTextSize = 0;
        this.frame = 0;
        this.frames = isLegacyConsole ? spinnerFramesCP437 : SpinnerFrames;
        this.interval = SpinnerFastInterval;
        this.state = SpinnerState.Stopped;
        this.timer = null;
        this.currentFrameWritten = false;
        this.stream = process.stderr;
        this.outputIsTty = process.stdout.isTTY && process.stderr.isTTY && !(process.env.TERM === "dumb");
    }
    clear() {
        if (!this.outputIsTty)
            return;
        cli_cursor_1.default.show(this.stream);
        readline.clearLine(this.stream, 0);
        readline.cursorTo(this.stream, 0);
        this.lastTextSize = 0;
    }
    getText() {
        return this.textSource ? this.textSource.getText() : "";
    }
    nextFrame() {
        switch (this.state) {
            case SpinnerState.Stopped:
                return this.handleStopped();
            case SpinnerState.Starting:
                return this.handleStarting();
            case SpinnerState.Paused:
                return this.handlePaused();
            case SpinnerState.Running:
                return this.handleRunning();
        }
    }
    handleStopped() {
        if (this.timer != null) {
            clearInterval(this.timer);
            this.timer = null;
        }
    }
    handleStarting() {
        if (this.timer == null) {
            this.interval = SpinnerFastInterval;
            this.timer = setInterval(() => this.timerCallback(), this.interval);
        }
        this.state = SpinnerState.Running;
    }
    handleRunning() {
        if (this.timer === null || this.interval === SpinnerFastInterval) {
            this.interval = SpinnerSlowInterval;
            if (this.timer != null)
                clearInterval(this.timer);
            this.timer = setInterval(() => this.timerCallback(), this.interval);
        }
        if (!this.outputIsTty)
            return;
        cli_cursor_1.default.hide(this.stream);
        readline.cursorTo(this.stream, 0);
        const text = this.getText();
        const sizeText = this.textSize(text);
        const trailing = sizeText < this.lastTextSize ? " ".repeat(this.lastTextSize - sizeText) : "";
        this.stream.write(chalk_1.default.cyan(this.frames[this.frame]) + " " + text + trailing);
        this.lastTextSize = sizeText;
        if (!this.currentFrameWritten)
            this.frame = (this.frame + 1) % this.frames.length;
        this.currentFrameWritten = true;
    }
    handlePaused() {
        if (this.timer != null) {
            clearInterval(this.timer);
            this.timer = null;
        }
    }
    timerCallback() {
        this.currentFrameWritten = false;
        this.nextFrame();
    }
    start() {
        if (this.state === SpinnerState.Running || this.state === SpinnerState.Starting)
            return;
        this.state = SpinnerState.Starting;
        this.nextFrame();
    }
    pause() {
        if (this.state === SpinnerState.Stopped || this.state === SpinnerState.Paused)
            return;
        if (this.state === SpinnerState.Running)
            this.clear();
        this.state = SpinnerState.Paused;
        this.nextFrame();
    }
    stop() {
        if (this.state === SpinnerState.Stopped)
            return;
        if (this.state === SpinnerState.Running)
            this.clear();
        this.state = SpinnerState.Stopped;
        this.nextFrame();
        this.stream.write(chalk_1.default.cyan(this.getText()));
    }
    textSize(t) {
        return t.replace(ansiRegex, "").length;
    }
}
exports.default = Spinner;
