function execOperation(type, action, url, $target, name) {
	const { clipBoard, $node, remove } = openFolder.find(url);
	const startLoading = () => $node.$title.classList.add("loading");
	const stopLoading = () => $node.$title.classList.remove("loading");

	switch (action) {
		case "copy":
		case "cut":
			return clipBoardAction();

		case "delete":
			return deleteFile();

		case "rename":
			return renameFile();

		case "paste":
			return paste();

		case "new file":
		case "new folder":
			return createNew();

		case "cancel":
			return cancelAction();

		case "open-folder":
			return open();

		case "insert-file":
			return insertFile();

		case "close":
			return remove();

		case "install-plugin":
			return installPlugin();
	}

	async function installPlugin() {
		try {
			const manifest = JSON.parse(
				await fsOperation(
					Url.dirname(url) + ACODE_PLUGIN_MANIFEST_FILE,
				).readFile("utf8"),
			);
			const { default: installPlugin } = await import("lib/installPlugin");
			await installPlugin(url, manifest.name);
			toast(strings["success"], 3000);
		} catch (error) {
			helpers.error(error);
			console.error(error);
		}
	}

	async function deleteFile() {
		const msg = strings["delete entry"].replace("{name}", name);
		const confirmation = await confirm(strings.warning, msg);
		if (!confirmation) return;
		startLoading();
		if (!(await fsOperation(url).exists())) return;
		// await fsOperation(url).delete();
		recents.removeFile(url);
		if (helpers.isFile(type)) {
			await fsOperation(url).delete();
			$target.remove();
			const file = editorManager.getFile(url, "uri");
			if (file) file.uri = null;
			editorManager.onupdate("delete-file");
			editorManager.emit("update", "delete-file");
		} else {
			if (url.startsWith("content://com.termux.documents/tree/")) {
				const fs = fsOperation(url);
				const entries = await fs.lsDir();
				if (entries.length === 0) {
					await fs.delete();
				} else {
					const deleteRecursively = async (currentUrl) => {
						const currentFs = fsOperation(currentUrl);
						const currentEntries = await currentFs.lsDir();
						for (const entry of currentEntries) {
							if (entry.isDirectory) {
								await deleteRecursively(entry.url);
							} else {
								await fsOperation(entry.url).delete();
							}
						}
						await currentFs.delete();
					};
					await deleteRecursively(url);
				}
			} else {
				await fsOperation(url).delete();
			}
			recents.removeFolder(url);
			helpers.updateUriOfAllActiveFiles(url, null);
			$target.parentElement.remove();
			editorManager.onupdate("delete-folder");
			editorManager.emit("update", "delete-folder");
		}

		toast(strings.success);
		FileList.remove(url);
	}

	async function renameFile() {
		if (
			url.startsWith("content://com.termux.documents/tree/") &&
			!helpers.isFile(type)
		) {
			alert(strings.warning, strings["rename not supported"]);
			return;
		}
		let newName = await prompt(strings.rename, name, "text", {
			match: constants.FILE_NAME_REGEX,
			required: true,
		});

		newName = helpers.fixFilename(newName);
		if (!newName || newName === name) return;

		startLoading();
		const fs = fsOperation(url);
		let newUrl;

		if (
			url.startsWith("content://com.termux.documents/tree/") &&
			helpers.isFile(type)
		) {
			// Special handling for Termux content files
			const newFilePath = Url.join(Url.dirname(url), newName);
			const content = await fs.readFile();
			await fsOperation(Url.dirname(url)).createFile(newName, content);
			await fs.delete();
			newUrl = newFilePath;
		} else {
			newUrl = await fs.renameTo(newName);
		}

		newName = Url.basename(newUrl);
		$target.querySelector(":scope>.text").textContent = newName;
		$target.dataset.url = newUrl;
		$target.dataset.name = newName;
		if (helpers.isFile(type)) {
			$target.querySelector(":scope>span").className =
				helpers.getIconForFile(newName);
			let file = editorManager.getFile(url, "uri");
			if (file) {
				file.uri = newUrl;
				file.filename = newName;
			}
		} else {
			helpers.updateUriOfAllActiveFiles(url, newUrl);
			//Reloading the folder by collapsing and expanding the folder
			$target.click(); //collapse
			$target.click(); //expand
		}
		toast(strings.success);
		FileList.rename(url, newUrl);
	}

	async function createNew() {
		const msg =
			action === "new file"
				? strings["enter file name"]
				: strings["enter folder name"];

		let newName = await prompt(msg, "", "text", {
			match: constants.FILE_NAME_REGEX,
			required: true,
		});

		newName = helpers.fixFilename(newName);
		if (!newName) return;
		startLoading();
		let newUrl;

		if (action === "new file") {
			newUrl = await helpers.createFileStructure(url, newName);
		} else {
			newUrl = await helpers.createFileStructure(url, newName, false);
		}
		if (!newUrl) return;
		newName = Url.basename(newUrl.uri);
		if ($target.unclasped) {
			if (newUrl.type === "file") {
				appendTile($target, createFileTile(newName, newUrl.uri));
			} else if (newUrl.type === "folder") {
				appendList($target, createFolderTile(newName, newUrl.uri));
			}
		}

		FileList.append(url, newUrl.uri);
		toast(strings.success);
	}

	async function paste() {
		if (clipBoard.url == null) {
			alert(strings.warning, "Nothing to paste");
			return;
		}

		let CASE = "";
		const $src = clipBoard.$el;
		const srcType = $src.dataset.type;
		const IS_FILE = helpers.isFile(srcType);
		const IS_DIR = helpers.isDir(srcType);
		const srcCollapsed = collapsed($src, IS_FILE);

		CASE += IS_FILE ? 1 : 0;
		CASE += srcCollapsed ? 1 : 0;
		CASE += $target.collapsed ? 1 : 0;

		startLoading();
		try {
			const fs = fsOperation(clipBoard.url);
			const itemName = Url.basename(clipBoard.url);
			const possibleConflictUrl = Url.join(url, itemName);
			const doesExist = await fsOperation(possibleConflictUrl).exists();
			if (doesExist) {
				alert(
					strings.error,
					strings["already exists"]
						? strings["already exists"].replace("{name}", itemName)
						: `"${itemName}" already exists in this location.`,
				);
				return;
			}
			let newUrl;
			if (clipBoard.action === "cut") newUrl = await fs.moveTo(url);
			else newUrl = await fs.copyTo(url);
			const { name: newName } = await fsOperation(newUrl).stat();
			stopLoading();
			/**
			 * CASES:
			 * CASE 111: src is file and parent is collapsed where target is also collapsed
			 * CASE 110: src is file and parent is collapsed where target is unclasped
			 * CASE 101: src is file and parent is unclasped where target is collapsed
			 * CASE 100: src is file and parent is unclasped where target is also unclasped
			 * CASE 011: src is directory and parent is collapsed where target is also collapsed
			 * CASE 001: src is directory and parent is unclasped where target is also collapsed
			 * CASE 010: src is directory and parent is collapsed where target is also unclasped
			 * CASE 000: src is directory and parent is unclasped where target is also unclasped
			 */

			if (clipBoard.action === "cut") {
				//move

				if (IS_FILE) {
					const file = editorManager.getFile(clipBoard.url, "uri");
					if (file) file.uri = newUrl;
				} else if (IS_DIR) {
					helpers.updateUriOfAllActiveFiles(clipBoard.url, newUrl);
				}

				switch (CASE) {
					case "111":
					case "011":
						break;

					case "110":
						appendTile($target, createFileTile(newName, newUrl));
						break;

					case "101":
						$src.remove();
						break;

					case "100":
						appendTile($target, createFileTile(newName, newUrl));
						$src.remove();
						break;

					case "001":
						$src.parentElement.remove();
						break;

					case "010":
						appendList($target, createFolderTile(newName, newUrl));
						break;

					case "000":
						appendList($target, createFolderTile(newName, newUrl));
						$src.parentElement.remove();
						break;

					default:
						break;
				}
				FileList.remove(clipBoard.url);
			} else {
				//copy

				switch (CASE) {
					case "111":
					case "101":
					case "011":
					case "001":
						break;

					case "110":
					case "100":
						appendTile($target, createFileTile(newName, newUrl));
						break;

					case "010":
					case "000":
						appendList($target, createFolderTile(newName, newUrl));
						break;

					default:
						break;
				}
			}

			FileList.append(url, newUrl);
			toast(strings.success);
			clearClipboard();
		} catch (error) {
			console.error(error);
			helpers.error(error);
		} finally {
			stopLoading();
		}
	}

	async function insertFile() {
		startLoading();
		try {
			const file = await FileBrowser("file", strings["insert file"]);
			const sourceFs = fsOperation(file.url);
			const data = await sourceFs.readFile();
			const sourceStats = await sourceFs.stat();
			const insertedFile = await fsOperation(url).createFile(
				sourceStats.name,
				data,
			);
			appendTile($target, createFileTile(sourceStats.name, insertedFile));
			FileList.append(url, insertedFile);
		} catch (error) {
		} finally {
			stopLoading();
		}
	}

	async function clipBoardAction() {
		clipBoard.url = url;
		clipBoard.action = action;
		clipBoard.$el = $target;

		if (action === "cut") $target.classList.add("cut");
		else $target.classList.remove("cut");
	}

	async function open() {
		FileBrowser.openFolder({
			url,
			name,
		});
	}

	function cancelAction() {
		clipBoard.$el.classList.remove("cut");
		clearClipboard();
	}

	function clearClipboard() {
		clipBoard.$el = null;
		clipBoard.url = null;
		clipBoard.action = null;
	}
}
@param {"dir"|"file"|"root"} type
@param {"copy"|"cut"|"delete"|"rename"|"paste"|"new file"|"new folder"|"cancel"|"open-folder"|"install-plugin"} action
@param {string} url target url
@param {HTMLElement} $target target element
@param {string} name Name of file or folder