import { __toESM } from "../../../_virtual/rolldown_runtime.js";
import { ok } from "../../devlop/lib/default.js";
import { bail } from "../../bail/index.js";
import { require_extend } from "../../extend/index.js";
import isPlainObject from "../node_modules/is-plain-obj/index.js";
import { trough } from "../../trough/lib/index.js";
import { VFile } from "../../vfile/lib/index.js";
import { CallableInstance } from "./callable-instance.js";
var import_extend = /* @__PURE__ */ __toESM(require_extend(), 1), own = {}.hasOwnProperty;
const unified = new class e extends CallableInstance {
	constructor() {
		super("copy"), this.Compiler = void 0, this.Parser = void 0, this.attachers = [], this.compiler = void 0, this.freezeIndex = -1, this.frozen = void 0, this.namespace = {}, this.parser = void 0, this.transformers = trough();
	}
	copy() {
		let f = new e(), p = -1;
		for (; ++p < this.attachers.length;) {
			let e = this.attachers[p];
			f.use(...e);
		}
		return f.data((0, import_extend.default)(!0, {}, this.namespace)), f;
	}
	data(e, f) {
		return typeof e == "string" ? arguments.length === 2 ? (assertUnfrozen("data", this.frozen), this.namespace[e] = f, this) : own.call(this.namespace, e) && this.namespace[e] || void 0 : e ? (assertUnfrozen("data", this.frozen), this.namespace = e, this) : this.namespace;
	}
	freeze() {
		if (this.frozen) return this;
		let e = this;
		for (; ++this.freezeIndex < this.attachers.length;) {
			let [f, ...p] = this.attachers[this.freezeIndex];
			if (p[0] === !1) continue;
			p[0] === !0 && (p[0] = void 0);
			let m = f.call(e, ...p);
			typeof m == "function" && this.transformers.use(m);
		}
		return this.frozen = !0, this.freezeIndex = Infinity, this;
	}
	parse(e) {
		this.freeze();
		let f = vfile(e), p = this.parser || this.Parser;
		return assertParser("parse", p), p(String(f), f);
	}
	process(e, f) {
		let p = this;
		return this.freeze(), assertParser("process", this.parser || this.Parser), assertCompiler("process", this.compiler || this.Compiler), f ? m(void 0, f) : new Promise(m);
		function m(m, h) {
			let g = vfile(e), _ = p.parse(g);
			p.run(_, g, function(e, f, m) {
				if (e || !f || !m) return v(e);
				let h = f, g = p.stringify(h, m);
				looksLikeAValue(g) ? m.value = g : m.result = g, v(e, m);
			});
			function v(e, p) {
				e || !p ? h(e) : m ? m(p) : f(void 0, p);
			}
		}
	}
	processSync(e) {
		let f = !1, m;
		return this.freeze(), assertParser("processSync", this.parser || this.Parser), assertCompiler("processSync", this.compiler || this.Compiler), this.process(e, h), assertDone("processSync", "process", f), m;
		function h(e, h) {
			f = !0, bail(e), m = h;
		}
	}
	run(e, f, p) {
		assertNode(e), this.freeze();
		let m = this.transformers;
		return !p && typeof f == "function" && (p = f, f = void 0), p ? h(void 0, p) : new Promise(h);
		function h(h, g) {
			let _ = vfile(f);
			m.run(e, _, v);
			function v(f, m, _) {
				let v = m || e;
				f ? g(f) : h ? h(v) : p(void 0, v, _);
			}
		}
	}
	runSync(e, f) {
		let m = !1, h;
		return this.run(e, f, g), assertDone("runSync", "run", m), h;
		function g(e, f) {
			bail(e), h = f, m = !0;
		}
	}
	stringify(e, f) {
		this.freeze();
		let p = vfile(f), m = this.compiler || this.Compiler;
		return assertCompiler("stringify", m), assertNode(e), m(e, p);
	}
	use(e, ...f) {
		let p = this.attachers, m = this.namespace;
		if (assertUnfrozen("use", this.frozen), e != null) if (typeof e == "function") y(e, f);
		else if (typeof e == "object") Array.isArray(e) ? v(e) : _(e);
		else throw TypeError("Expected usable value, not `" + e + "`");
		return this;
		function g(e) {
			if (typeof e == "function") y(e, []);
			else if (typeof e == "object") if (Array.isArray(e)) {
				let [f, ...p] = e;
				y(f, p);
			} else _(e);
			else throw TypeError("Expected usable value, not `" + e + "`");
		}
		function _(e) {
			if (!("plugins" in e) && !("settings" in e)) throw Error("Expected usable value but received an empty preset, which is probably a mistake: presets typically come with `plugins` and sometimes with `settings`, but this has neither");
			v(e.plugins), e.settings && (m.settings = (0, import_extend.default)(!0, m.settings, e.settings));
		}
		function v(e) {
			let f = -1;
			if (e != null) if (Array.isArray(e)) for (; ++f < e.length;) {
				let p = e[f];
				g(p);
			}
			else throw TypeError("Expected a list of plugins, not `" + e + "`");
		}
		function y(e, f) {
			let m = -1, g = -1;
			for (; ++m < p.length;) if (p[m][0] === e) {
				g = m;
				break;
			}
			if (g === -1) p.push([e, ...f]);
			else if (f.length > 0) {
				let [m, ..._] = f, v = p[g][1];
				isPlainObject(v) && isPlainObject(m) && (m = (0, import_extend.default)(!0, v, m)), p[g] = [
					e,
					m,
					..._
				];
			}
		}
	}
}().freeze();
function assertParser(e, f) {
	if (typeof f != "function") throw TypeError("Cannot `" + e + "` without `parser`");
}
function assertCompiler(e, f) {
	if (typeof f != "function") throw TypeError("Cannot `" + e + "` without `compiler`");
}
function assertUnfrozen(e, f) {
	if (f) throw Error("Cannot call `" + e + "` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.");
}
function assertNode(e) {
	if (!isPlainObject(e) || typeof e.type != "string") throw TypeError("Expected node, got `" + e + "`");
}
function assertDone(e, f, p) {
	if (!p) throw Error("`" + e + "` finished async. Use `" + f + "` instead");
}
function vfile(e) {
	return looksLikeAVFile(e) ? e : new VFile(e);
}
function looksLikeAVFile(e) {
	return !!(e && typeof e == "object" && "message" in e && "messages" in e);
}
function looksLikeAValue(e) {
	return typeof e == "string" || isUint8Array(e);
}
function isUint8Array(e) {
	return !!(e && typeof e == "object" && "byteLength" in e && "byteOffset" in e);
}
export { unified };
