import * as tsplus_module_1 from "@tsplus/stdlib/collections/Chunk/definition";
import * as tsplus_module_2 from "@tsplus/stdlib/collections/Chunk/size";
import * as tsplus_module_3 from "@tsplus/stdlib/collections/Chunk/unsafeGet";
import * as tsplus_module_4 from "@tsplus/stdlib/collections/Chunk/drop";
import * as tsplus_module_5 from "@tsplus/stdlib/collections/Chunk/empty";
import * as tsplus_module_6 from "@tsplus/stdlib/collections/Chunk/builder";
import { Subscription } from "@effect/core/io/Hub/operations/_internal/Subscription";
export class BoundedHubArb {
  constructor(requestedCapacity) {
    this.publisherIndex = 0;
    this.subscriberCount = 0;
    this.subscribersIndex = 0;
    this.array = Array.from({
      length: requestedCapacity
    });
    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.capacity;
      this.array[index] = a;
      this.subscribers[index] = this.subscriberCount;
      this.publisherIndex += 1;
    }

    return true;
  }

  publishAll(as) {
    const asArray = tsplus_module_1.from(as);
    const n = tsplus_module_2.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 = tsplus_module_3.unsafeGet_(asArray, iteratorIndex++);
      const index = this.publisherIndex % this.capacity;
      this.array[index] = a;
      this.subscribers[index] = this.subscriberCount;
      this.publisherIndex += 1;
    }

    return tsplus_module_4.drop_(asArray, iteratorIndex - 1);
  }

  size() {
    return this.publisherIndex - this.subscribersIndex;
  }

  slide() {
    if (this.subscribersIndex !== this.publisherIndex) {
      const index = this.subscribersIndex % this.capacity;
      this.array[index] = null;
      this.subscribers[index] = 0;
      this.subscribersIndex += 1;
    }
  }

  subscribe() {
    this.subscriberCount += 1;
    return new BoundedHubArbSubscription(this, this.publisherIndex, false);
  }

}

class BoundedHubArbSubscription extends 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.capacity;
      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 tsplus_module_5.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 tsplus_module_5.empty();
    }

    const builder = tsplus_module_6.builder();
    const pollUpToIndex = this.subscriberIndex + toPoll;

    while (this.subscriberIndex !== pollUpToIndex) {
      const index = this.subscriberIndex % this.self.capacity;
      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;
      }

      builder.append(a);
      this.subscriberIndex += 1;
    }

    return builder.build();
  }

  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.capacity;
        this.self.subscribers[index] -= 1;

        if (this.self.subscribers[index] === 0) {
          this.self.array[index] = null;
          this.self.subscribersIndex += 1;
        }

        this.subscriberIndex += 1;
      }
    }
  }

}
//# sourceMappingURL=BoundedHubArb.mjs.map