import { MERKLE_LEVELS as e } from "../../constants/protocol.constants.mjs";
import { logError as t } from "../../error-handling/logError.mjs";
import { MerkleTreeIncompleteError as n } from "./MerkleTreeIncompleteError.mjs";
//#region libs/shared/common/src/data-structures/merkle-tree/MerkleTree.ts
var r = class r {
	tree;
	count;
	index;
	reverseTree;
	static createWithData(e, t, n, i, a, o, s) {
		return new r(a, o, s, e, t, n, i);
	}
	static create(t, n, i = e) {
		return new r(t, i, n);
	}
	createReverseTree() {
		let e = /* @__PURE__ */ new Map();
		for (let t = this.getStartIndex(); t < this.getStartIndex() + this.count; t += 1n) {
			let n = this.tree.get(t);
			n !== void 0 && e.set(n, t);
		}
		return e;
	}
	constructor(e, t, n, r, i, a, o) {
		this.hashFunction = e, this.levels = t, this.defaultNodeValue = n, this.tree = r ?? /* @__PURE__ */ new Map(), this.count = o ?? 0n, this.index = a ?? 2n ** (t - 1n), i ? this.reverseTree = i : this.reverseTree = this.createReverseTree();
	}
	getStartIndex() {
		return 2n ** (this.levels - 1n);
	}
	logarithm2(e) {
		let t = 0n;
		for (; 2n ** t < e;) t += 1n;
		return t;
	}
	bigIntMax(e, t) {
		return e > t ? e : t;
	}
	forceInsert(e, t) {
		if (t < this.getStartIndex()) throw RangeError();
		this.tree.set(t, e), this.reverseTree.set(e, t);
		let n = this.index - this.getStartIndex(), r = this.logarithm2(n), i = t;
		for (let e = 1n; e <= r; e += 1n) {
			i /= 2n;
			let e = this.hashFunction(this.tree.get(i * 2n) || this.defaultNodeValue, this.tree.get(i * 2n + 1n) || this.defaultNodeValue);
			this.tree.set(i, e);
		}
	}
	insert(e, n) {
		let r = !1;
		this.tree.has(n) && (r = !0, t(`Editing commitment index: ${n} `)), r || (this.count += 1n), this.index = this.bigIntMax(this.index, n + 1n), this.forceInsert(e, n);
	}
	remove(e) {
		this.forceInsert(this.defaultNodeValue, e);
	}
	completenessCheck() {
		if (this.count !== this.index - this.getStartIndex()) throw new n();
	}
	getRootHash() {
		this.completenessCheck();
		for (let e = 1n; e < 2n ** this.levels; e *= 2n) if (this.tree.get(e)) return this.tree.get(e);
		return this.defaultNodeValue;
	}
	getMerkleData() {
		return this.completenessCheck(), new Map(this.tree);
	}
	getValue(e) {
		return this.tree.get(e);
	}
	getSiblingIndex(e) {
		return e === 1n ? 1n : e % 2n == 1n ? e - 1n : e + 1n;
	}
	getSiblingHashesForVerification(e) {
		this.completenessCheck();
		let t = this.reverseTree.get(e);
		if (t === void 0) return Array(25).fill(0n);
		let n = [];
		for (; t !== 0n;) n.push(this.tree.get(this.getSiblingIndex(t)) || this.defaultNodeValue), t /= 2n;
		return n.slice(0, 25);
	}
	getSiblingSides(e) {
		this.completenessCheck();
		let t = this.reverseTree.get(e);
		if (t === void 0) return Array(25).fill(0n);
		let n = [];
		for (; t !== 0n;) {
			let e = t % 2n == 0n ? 0n : 1n;
			n.push(e), t /= 2n;
		}
		return n.slice(0, 25);
	}
	toJSON() {
		let { tree: e, reverseTree: t, count: n, index: r } = this;
		return {
			tree: Object.fromEntries(e),
			reverseTree: Object.fromEntries(t),
			count: n.toString(),
			index: r.toString()
		};
	}
	toJSONLite() {
		let { tree: e, count: t, index: n } = this;
		return {
			tree: Object.fromEntries(e),
			count: t.toString(),
			index: n.toString()
		};
	}
	clone() {
		return r.createWithData(new Map(this.tree), new Map(this.reverseTree), this.index, this.count, this.hashFunction, this.levels, this.defaultNodeValue);
	}
	getIndex() {
		return this.index;
	}
};
//#endregion
export { r as MerkleTree };
