"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.toFinishingSafe = exports.toFinishing = exports.withInterrupting = exports.withInterruptingSafe = exports.isDone = exports.Suspended = exports.Running = exports.Finishing = exports.Done = void 0;
// ets_tracing: off
const St = __importStar(require("../Structural"));
const S = __importStar(require("../Sync"));
class Done {
    constructor() {
        this._tag = "Done";
    }
    get [St.hashSym]() {
        return St.hashString(this._tag);
    }
    [St.equalsSym](that) {
        return that instanceof Done;
    }
}
exports.Done = Done;
class Finishing {
    constructor(interrupting) {
        this.interrupting = interrupting;
        this._tag = "Finishing";
    }
    get [St.hashSym]() {
        return St.combineHash(St.hashString(this._tag), St.hash(this.interrupting));
    }
    [St.equalsSym](that) {
        return that instanceof Finishing && this.interrupting === that.interrupting;
    }
}
exports.Finishing = Finishing;
class Running {
    constructor(interrupting) {
        this.interrupting = interrupting;
        this._tag = "Running";
    }
    get [St.hashSym]() {
        return St.combineHash(St.hashString(this._tag), St.hash(this.interrupting));
    }
    [St.equalsSym](that) {
        return that instanceof Running && this.interrupting === that.interrupting;
    }
}
exports.Running = Running;
class Suspended {
    constructor(previous, interruptible, epoch, blockingOn) {
        this.previous = previous;
        this.interruptible = interruptible;
        this.epoch = epoch;
        this.blockingOn = blockingOn;
        this._tag = "Suspended";
    }
    get [St.hashSym]() {
        return St.combineHash(St.combineHash(St.hashString(this._tag), St.hashPlainObject({
            previous: this.previous,
            interruptible: this.interruptible,
            epoch: this.epoch
        })), St.hashArray(this.blockingOn));
    }
    [St.equalsSym](that) {
        return (that instanceof Suspended &&
            St.equals(this.previous, that.previous) &&
            this.interruptible === that.interruptible &&
            this.epoch === that.epoch &&
            this.eqArr(this.blockingOn, that.blockingOn));
    }
    eqArr(a, b) {
        if (a.length !== b.length) {
            return false;
        }
        return a.every((v, i) => St.equals(v, b[i]));
    }
}
exports.Suspended = Suspended;
function isDone(s) {
    return s._tag === "Done";
}
exports.isDone = isDone;
function withInterruptingSafe(b) {
    return (s) => {
        return S.gen(function* (_) {
            switch (s._tag) {
                case "Done": {
                    return s;
                }
                case "Finishing": {
                    return new Finishing(b);
                }
                case "Running": {
                    return new Running(b);
                }
                case "Suspended": {
                    return new Suspended(yield* _(withInterruptingSafe(b)(s.previous)), s.interruptible, s.epoch, s.blockingOn);
                }
            }
        });
    };
}
exports.withInterruptingSafe = withInterruptingSafe;
function withInterrupting(b) {
    return (s) => S.run(withInterruptingSafe(b)(s));
}
exports.withInterrupting = withInterrupting;
function toFinishing(s) {
    return S.run(toFinishingSafe(s));
}
exports.toFinishing = toFinishing;
function toFinishingSafe(s) {
    return S.gen(function* (_) {
        switch (s._tag) {
            case "Done": {
                return s;
            }
            case "Finishing": {
                return s;
            }
            case "Running": {
                return s;
            }
            case "Suspended": {
                return yield* _(toFinishingSafe(s.previous));
            }
        }
    });
}
exports.toFinishingSafe = toFinishingSafe;
//# sourceMappingURL=status.js.map