/* eslint-disable import/prefer-default-export */

import { splitCommandString } from '@joplin/utils';
import { spawn } from 'child_process';
import Logger from '@joplin/utils/Logger';
import Setting from '../../models/Setting';
import { fileExtension } from '../../path-utils';
import shim from '../../shim';

const logger = Logger.create('ExternalEditWatcher/utils');

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
const spawnCommand = async (path: string, args: string[], options: any) => {
	return new Promise((resolve, reject) => {
		// App bundles need to be opened using the `open` command.
		// Additional args can be specified after --args, and the
		// -n flag is needed to ensure that the app is always launched
		// with the arguments. Without it, if the app is already opened,
		// it will just bring it to the foreground without opening the file.
		// So the full command is:
		//
		// open -n /path/to/editor.app --args -app-flag -bla /path/to/file.md
		//
		if (shim.isMac() && fileExtension(path) === 'app') {
			args = args.slice();
			args.splice(0, 0, '--args');
			args.splice(0, 0, path);
			args.splice(0, 0, '-n');
			path = 'open';
		}

		// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
		const wrapError = (error: any) => {
			if (!error) return error;
			const msg = error.message ? [error.message] : [];
			msg.push(`Command was: "${path}" ${args.join(' ')}`);
			error.message = msg.join('\n\n');
			return error;
		};

		try {
			const subProcess = spawn(path, args, options);

			const iid = shim.setInterval(() => {
				if (subProcess && subProcess.pid) {
					logger.debug(`Started editor with PID ${subProcess.pid}`);
					shim.clearInterval(iid);
					resolve(null);
				}
			}, 100);

			// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
			subProcess.on('error', (error: any) => {
				shim.clearInterval(iid);
				reject(wrapError(error));
			});
		} catch (error) {
			throw wrapError(error);
		}
	});
};

const textEditorCommand = () => {
	const editorCommand = Setting.value('editor');
	if (!editorCommand) return null;

	const s = splitCommandString(editorCommand, { handleEscape: false });
	const path = s.splice(0, 1);
	if (!path.length) throw new Error(`Invalid editor command: ${editorCommand}`);

	return {
		path: path[0],
		args: s,
	};
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
export const openFileWithExternalEditor = async (filePath: string, bridge: any) => {
	const cmd = textEditorCommand();
	if (!cmd) {
		bridge.openItem(filePath);
	} else {
		cmd.args.push(filePath);
		await spawnCommand(cmd.path, cmd.args, { detached: true });
	}
};
