import { a as e, n as t, o as n } from "./definitions-ySQKlM5C-LQwO0-Ud.js";
//#region node_modules/@amsom-habitat/ui/dist/web-CNQ_BV_h.js
function r(e) {
	let t = e.split("/").filter((e) => e !== "."), n = [];
	return t.forEach((e) => {
		e === ".." && n.length > 0 && n[n.length - 1] !== ".." ? n.pop() : n.push(e);
	}), n.join("/");
}
function i(e, t) {
	e = r(e), t = r(t);
	let n = e.split("/"), i = t.split("/");
	return e !== t && n.every((e, t) => e === i[t]);
}
var a = class r extends e {
	constructor() {
		super(...arguments), this.DB_VERSION = 1, this.DB_NAME = "Disc", this._writeCmds = [
			"add",
			"put",
			"delete"
		], this.downloadFile = async (e) => {
			let t = n(e, e.webFetchExtra), r = await fetch(e.url, t), i;
			if (!e.progress) i = await r.blob();
			else if (!r?.body) i = new Blob();
			else {
				let t = r.body.getReader(), n = 0, a = [], o = r.headers.get("content-type"), s = parseInt(r.headers.get("content-length") || "0", 10);
				for (;;) {
					let { done: r, value: i } = await t.read();
					if (r) break;
					a.push(i), n += i?.length || 0;
					let o = {
						url: e.url,
						bytes: n,
						contentLength: s
					};
					this.notifyListeners("progress", o);
				}
				let c = new Uint8Array(n), l = 0;
				for (let e of a) e !== void 0 && (c.set(e, l), l += e.length);
				i = new Blob([c.buffer], { type: o || void 0 });
			}
			return {
				path: (await this.writeFile({
					path: e.path,
					directory: e.directory ?? void 0,
					recursive: e.recursive ?? !1,
					data: i
				})).uri,
				blob: i
			};
		};
	}
	readFileInChunks(e, t) {
		throw this.unavailable("Method not implemented.");
	}
	async initDb() {
		if (this._db !== void 0) return this._db;
		if (!("indexedDB" in window)) throw this.unavailable("This browser doesn't support IndexedDB");
		return new Promise((e, t) => {
			let n = indexedDB.open(this.DB_NAME, this.DB_VERSION);
			n.onupgradeneeded = r.doUpgrade, n.onsuccess = () => {
				this._db = n.result, e(n.result);
			}, n.onerror = () => t(n.error), n.onblocked = () => {
				console.warn("db blocked");
			};
		});
	}
	static doUpgrade(e) {
		let t = e.target.result;
		switch (e.oldVersion) {
			default: t.objectStoreNames.contains("FileStorage") && t.deleteObjectStore("FileStorage"), t.createObjectStore("FileStorage", { keyPath: "path" }).createIndex("by_folder", "folder");
		}
	}
	async dbRequest(e, t) {
		let n = this._writeCmds.indexOf(e) === -1 ? "readonly" : "readwrite";
		return this.initDb().then((r) => new Promise((i, a) => {
			let o = r.transaction(["FileStorage"], n).objectStore("FileStorage")[e](...t);
			o.onsuccess = () => i(o.result), o.onerror = () => a(o.error);
		}));
	}
	async dbIndexRequest(e, t, n) {
		let r = this._writeCmds.indexOf(t) === -1 ? "readonly" : "readwrite";
		return this.initDb().then((i) => new Promise((a, o) => {
			let s = i.transaction(["FileStorage"], r).objectStore("FileStorage").index(e)[t](...n);
			s.onsuccess = () => a(s.result), s.onerror = () => o(s.error);
		}));
	}
	getPath(e, t) {
		let n = t === void 0 ? "" : t.replace(/^[/]+|[/]+$/g, ""), r = "";
		return e !== void 0 && (r += "/" + e), t !== "" && (r += "/" + n), r;
	}
	async clear() {
		(await this.initDb()).transaction(["FileStorage"], "readwrite").objectStore("FileStorage").clear();
	}
	async readFile(e) {
		let t = this.getPath(e.directory, e.path), n = await this.dbRequest("get", [t]);
		if (n === void 0) throw Error("File does not exist.");
		return { data: n.content ? n.content : "" };
	}
	async writeFile(e) {
		let t = this.getPath(e.directory, e.path), n = e.data, r = e.encoding, i = e.recursive, a = await this.dbRequest("get", [t]);
		if (a && a.type === "directory") throw Error("The supplied path is a directory.");
		let o = t.substr(0, t.lastIndexOf("/"));
		if (await this.dbRequest("get", [o]) === void 0) {
			let t = o.indexOf("/", 1);
			if (t !== -1) {
				let n = o.substr(t);
				await this.mkdir({
					path: n,
					directory: e.directory,
					recursive: i
				});
			}
		}
		if (!r && !(n instanceof Blob) && (n = n.indexOf(",") >= 0 ? n.split(",")[1] : n, !this.isBase64String(n))) throw Error("The supplied data is not valid base64 content.");
		let s = Date.now(), c = {
			path: t,
			folder: o,
			type: "file",
			size: n instanceof Blob ? n.size : n.length,
			ctime: s,
			mtime: s,
			content: n
		};
		return await this.dbRequest("put", [c]), { uri: c.path };
	}
	async appendFile(e) {
		let t = this.getPath(e.directory, e.path), n = e.data, r = e.encoding, i = t.substr(0, t.lastIndexOf("/")), a = Date.now(), o = a, s = await this.dbRequest("get", [t]);
		if (s && s.type === "directory") throw Error("The supplied path is a directory.");
		if (await this.dbRequest("get", [i]) === void 0) {
			let t = i.indexOf("/", 1);
			if (t !== -1) {
				let n = i.substr(t);
				await this.mkdir({
					path: n,
					directory: e.directory,
					recursive: !0
				});
			}
		}
		if (!r && !this.isBase64String(n)) throw Error("The supplied data is not valid base64 content.");
		if (s !== void 0) {
			if (s.content instanceof Blob) throw Error("The occupied entry contains a Blob object which cannot be appended to.");
			n = s.content !== void 0 && !r ? btoa(atob(s.content) + atob(n)) : s.content + n, o = s.ctime;
		}
		let c = {
			path: t,
			folder: i,
			type: "file",
			size: n.length,
			ctime: o,
			mtime: a,
			content: n
		};
		await this.dbRequest("put", [c]);
	}
	async deleteFile(e) {
		let t = this.getPath(e.directory, e.path);
		if (await this.dbRequest("get", [t]) === void 0) throw Error("File does not exist.");
		if ((await this.dbIndexRequest("by_folder", "getAllKeys", [IDBKeyRange.only(t)])).length !== 0) throw Error("Folder is not empty.");
		await this.dbRequest("delete", [t]);
	}
	async mkdir(e) {
		let t = this.getPath(e.directory, e.path), n = e.recursive, r = t.substr(0, t.lastIndexOf("/")), i = (t.match(/\//g) || []).length, a = await this.dbRequest("get", [r]), o = await this.dbRequest("get", [t]);
		if (i === 1) throw Error("Cannot create Root directory");
		if (o !== void 0) throw Error("Current directory does already exist.");
		if (!n && i !== 2 && a === void 0) throw Error("Parent directory must exist");
		if (n && i !== 2 && a === void 0) {
			let t = r.substr(r.indexOf("/", 1));
			await this.mkdir({
				path: t,
				directory: e.directory,
				recursive: n
			});
		}
		let s = Date.now(), c = {
			path: t,
			folder: r,
			type: "directory",
			size: 0,
			ctime: s,
			mtime: s
		};
		await this.dbRequest("put", [c]);
	}
	async rmdir(e) {
		let { path: t, directory: n, recursive: r } = e, i = this.getPath(n, t), a = await this.dbRequest("get", [i]);
		if (a === void 0) throw Error("Folder does not exist.");
		if (a.type !== "directory") throw Error("Requested path is not a directory");
		let o = await this.readdir({
			path: t,
			directory: n
		});
		if (o.files.length !== 0 && !r) throw Error("Folder is not empty");
		for (let e of o.files) {
			let i = `${t}/${e.name}`;
			(await this.stat({
				path: i,
				directory: n
			})).type === "file" ? await this.deleteFile({
				path: i,
				directory: n
			}) : await this.rmdir({
				path: i,
				directory: n,
				recursive: r
			});
		}
		await this.dbRequest("delete", [i]);
	}
	async readdir(e) {
		let t = this.getPath(e.directory, e.path), n = await this.dbRequest("get", [t]);
		if (e.path !== "" && n === void 0) throw Error("Folder does not exist.");
		let r = await this.dbIndexRequest("by_folder", "getAllKeys", [IDBKeyRange.only(t)]);
		return { files: await Promise.all(r.map(async (e) => {
			let n = await this.dbRequest("get", [e]);
			return n === void 0 && (n = await this.dbRequest("get", [e + "/"])), {
				name: e.substring(t.length + 1),
				type: n.type,
				size: n.size,
				ctime: n.ctime,
				mtime: n.mtime,
				uri: n.path
			};
		})) };
	}
	async getUri(e) {
		let t = this.getPath(e.directory, e.path), n = await this.dbRequest("get", [t]);
		return n === void 0 && (n = await this.dbRequest("get", [t + "/"])), { uri: n?.path || t };
	}
	async stat(e) {
		let t = this.getPath(e.directory, e.path), n = await this.dbRequest("get", [t]);
		if (n === void 0 && (n = await this.dbRequest("get", [t + "/"])), n === void 0) throw Error("Entry does not exist.");
		return {
			name: n.path.substring(t.length + 1),
			type: n.type,
			size: n.size,
			ctime: n.ctime,
			mtime: n.mtime,
			uri: n.path
		};
	}
	async rename(e) {
		await this._copy(e, !0);
	}
	async copy(e) {
		return this._copy(e, !1);
	}
	async requestPermissions() {
		return { publicStorage: "granted" };
	}
	async checkPermissions() {
		return { publicStorage: "granted" };
	}
	async _copy(e, n = !1) {
		let { toDirectory: r } = e, { to: a, from: o, directory: s } = e;
		if (!a || !o) throw Error("Both to and from must be provided");
		r ||= s;
		let c = this.getPath(s, o), l = this.getPath(r, a);
		if (c === l) return { uri: l };
		if (i(c, l)) throw Error("To path cannot contain the from path");
		let u;
		try {
			u = await this.stat({
				path: a,
				directory: r
			});
		} catch {
			let e = a.split("/");
			e.pop();
			let t = e.join("/");
			if (e.length > 0 && (await this.stat({
				path: t,
				directory: r
			})).type !== "directory") throw Error("Parent directory of the to path is a file");
		}
		if (u && u.type === "directory") throw Error("Cannot overwrite a directory with a file");
		let d = await this.stat({
			path: o,
			directory: s
		}), f = async (e, t, n) => {
			let i = this.getPath(r, e), a = await this.dbRequest("get", [i]);
			a.ctime = t, a.mtime = n, await this.dbRequest("put", [a]);
		}, p = d.ctime ? d.ctime : Date.now();
		switch (d.type) {
			case "file": {
				let e = await this.readFile({
					path: o,
					directory: s
				});
				n && await this.deleteFile({
					path: o,
					directory: s
				});
				let i;
				!(e.data instanceof Blob) && !this.isBase64String(e.data) && (i = t.UTF8);
				let c = await this.writeFile({
					path: a,
					directory: r,
					data: e.data,
					encoding: i
				});
				return n && await f(a, p, d.mtime), c;
			}
			case "directory": {
				if (u) throw Error("Cannot move a directory over an existing object");
				try {
					await this.mkdir({
						path: a,
						directory: r,
						recursive: !1
					}), n && await f(a, p, d.mtime);
				} catch {}
				let e = (await this.readdir({
					path: o,
					directory: s
				})).files;
				for (let t of e) await this._copy({
					from: `${o}/${t.name}`,
					to: `${a}/${t.name}`,
					directory: s,
					toDirectory: r
				}, n);
				n && await this.rmdir({
					path: o,
					directory: s
				});
			}
		}
		return { uri: l };
	}
	isBase64String(e) {
		try {
			return btoa(atob(e)) == e;
		} catch {
			return !1;
		}
	}
};
a._debug = !0;
//#endregion
export { a as FilesystemWeb };
