"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Heap = void 0;
const parent = (i) => ((i + 1) >>> 1) - 1;
const left = (i) => (i << 1) + 1;
const right = (i) => (i + 1) << 1;
class Heap {
    constructor(comparator) {
        this.comparator = comparator;
        this.heap = [];
    }
    push(...values) {
        for (const item of values) {
            this.heap.push(item);
            this.siftUp();
        }
        return this;
    }
    peek() {
        return this.heap[0];
    }
    pop() {
        const poppedValue = this.peek();
        const bottom = this.size - 1;
        if (bottom > 0) {
            this.swap(0, bottom);
        }
        this.heap.pop();
        this.siftDown();
        return poppedValue;
    }
    replace(value) {
        const replacedValue = this.peek();
        this.heap[0] = value;
        this.siftDown();
        return replacedValue;
    }
    clear() {
        this.heap = [];
    }
    toArray() {
        return this.heap;
    }
    get size() {
        return this.heap.length;
    }
    greater(i, j) {
        return this.comparator(this.heap[i], this.heap[j]);
    }
    swap(i, j) {
        [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
    }
    siftUp() {
        let node = this.size - 1;
        while (node > 0 && this.greater(node, parent(node))) {
            this.swap(node, parent(node));
            node = parent(node);
        }
    }
    siftDown() {
        let node = 0;
        while ((left(node) < this.size && this.greater(left(node), node)) ||
            (right(node) < this.size && this.greater(right(node), node))) {
            const maxChild = right(node) < this.size && this.greater(right(node), left(node)) ? right(node) : left(node);
            this.swap(node, maxChild);
            node = maxChild;
        }
    }
}
exports.Heap = Heap;
