"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.BoundedHubPow2 = void 0;
// ets_tracing: off
require("../../Operator");
const Chunk = __importStar(require("../../Collections/Immutable/Chunk"));
const Hub_1 = require("./Hub");
class BoundedHubPow2 extends Hub_1.Hub {
    constructor(requestedCapacity) {
        super();
        this.publisherIndex = 0;
        this.subscriberCount = 0;
        this.subscribersIndex = 0;
        this.array = Array.from({ length: requestedCapacity });
        this.mask = requestedCapacity = 1;
        this.subscribers = Array.from({ length: requestedCapacity });
        this.capacity = requestedCapacity;
    }
    isEmpty() {
        return this.publisherIndex === this.subscribersIndex;
    }
    isFull() {
        return this.publisherIndex === this.subscribersIndex + this.capacity;
    }
    publish(a) {
        if (this.isFull()) {
            return false;
        }
        if (this.subscriberCount !== 0) {
            const index = this.publisherIndex & this.mask;
            this.array[index] = a;
            this.subscribers[index] = this.subscriberCount;
            this.publisherIndex += 1;
        }
        return true;
    }
    publishAll(as) {
        const asArray = Chunk.from(as);
        const n = Chunk.size(asArray);
        const size = this.publisherIndex - this.subscribersIndex;
        const available = this.capacity - size;
        const forHub = Math.min(n, available);
        if (forHub === 0) {
            return asArray;
        }
        let iteratorIndex = 0;
        const publishAllIndex = this.publisherIndex + forHub;
        while (this.publisherIndex !== publishAllIndex) {
            const a = asArray[iteratorIndex++];
            const index = this.publisherIndex & this.mask;
            this.array[index] = a;
            this.publisherIndex += 1;
        }
        return Chunk.drop_(asArray, iteratorIndex - 1);
    }
    size() {
        return this.publisherIndex - this.subscribersIndex;
    }
    slide() {
        if (this.subscribersIndex !== this.publisherIndex) {
            const index = this.subscribersIndex & this.mask;
            this.array[index] = null;
            this.subscribers[index] = 0;
            this.subscribersIndex += 1;
        }
    }
    subscribe() {
        this.subscriberCount += 1;
        return new BoundedHubPow2Subcription(this, this.publisherIndex, false);
    }
}
exports.BoundedHubPow2 = BoundedHubPow2;
class BoundedHubPow2Subcription extends Hub_1.Subscription {
    constructor(self, subscriberIndex, unsubscribed) {
        super();
        this.self = self;
        this.subscriberIndex = subscriberIndex;
        this.unsubscribed = unsubscribed;
    }
    isEmpty() {
        return (this.unsubscribed ||
            this.self.publisherIndex === this.subscriberIndex ||
            this.self.publisherIndex === this.self.subscribersIndex);
    }
    poll(default_) {
        if (this.unsubscribed) {
            return default_;
        }
        this.subscriberIndex = Math.max(this.subscriberIndex, this.self.subscribersIndex);
        if (this.subscriberIndex !== this.self.publisherIndex) {
            const index = this.subscriberIndex & this.self.mask;
            const a = this.self.array[index];
            this.self.subscribers[index] -= 1;
            if (this.self.subscribers[index] === 0) {
                this.self.array[index] = null;
                this.self.subscribersIndex += 1;
            }
            this.subscriberIndex += 1;
            return a;
        }
        return default_;
    }
    pollUpTo(n) {
        if (this.unsubscribed) {
            return Chunk.empty();
        }
        this.subscriberIndex = Math.max(this.subscriberIndex, this.self.subscribersIndex);
        const size = this.self.publisherIndex - this.subscriberIndex;
        const toPoll = Math.min(n, size);
        if (toPoll <= 0) {
            return Chunk.empty();
        }
        let builder = Chunk.empty();
        const pollUpToIndex = this.subscriberIndex + toPoll;
        while (this.subscriberIndex !== pollUpToIndex) {
            const index = this.subscriberIndex & this.self.mask;
            const a = this.self.array[index];
            builder = Chunk.append_(builder, a);
            this.subscriberIndex += 1;
        }
        return builder;
    }
    size() {
        if (this.unsubscribed) {
            return 0;
        }
        return (this.self.publisherIndex -
            Math.max(this.subscriberIndex, this.self.subscribersIndex));
    }
    unsubscribe() {
        if (!this.unsubscribed) {
            this.unsubscribed = true;
            this.self.subscriberCount -= 1;
            this.subscriberIndex = Math.max(this.subscriberIndex, this.self.subscribersIndex);
            while (this.subscriberIndex < this.self.publisherIndex) {
                const index = this.subscriberIndex & this.self.mask;
                this.self.subscribers[index] -= 1;
                if (this.self.subscribers[index] === 0) {
                    this.self.array[index] = null;
                    this.self.subscribersIndex += 1;
                }
                this.subscriberIndex += 1;
            }
        }
    }
}
//# sourceMappingURL=BoundedHubPow2.js.map