import { RefObject, useCallback } from 'react';
import { FormNote, HtmlToMarkdownHandler, MarkupToHtmlHandler, ScrollOptions, MessageEvent } from './types';
import contextMenu from './contextMenu';
import CommandService from '@joplin/lib/services/CommandService';
import PostMessageService from '@joplin/lib/services/PostMessageService';
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
import { reg } from '@joplin/lib/registry';
import bridge from '../../../services/bridge';
import { resolveContextMenuItemType } from './contextMenuUtils';

export default function useMessageHandler(
	scrollWhenReadyRef: RefObject<ScrollOptions|null>,
	clearScrollWhenReady: ()=> void,
	windowId: string,
	// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
	editorRef: any,
	// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
	setLocalSearchResultCount: Function,
	// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
	dispatch: Function,
	formNote: FormNote,
	htmlToMd: HtmlToMarkdownHandler,
	mdToHtml: MarkupToHtmlHandler,
) {
	return useCallback(async (event: MessageEvent) => {
		const msg = event.channel ? event.channel : '';
		const args = event.args;
		const arg0 = args && args.length >= 1 ? args[0] : null;

		// eslint-disable-next-line no-console
		if (msg !== 'percentScroll') console.info(`Got ipc-message: ${msg}`, arg0);

		if (msg.indexOf('error:') === 0) {
			const s = msg.split(':');
			s.splice(0, 1);
			reg.logger().error(s.join(':'));
		} else if (msg === 'noteRenderComplete') {
			if (scrollWhenReadyRef.current) {
				const options = { ...scrollWhenReadyRef.current };
				clearScrollWhenReady();
				editorRef.current.scrollTo(options);
			}
		} else if (msg === 'setMarkerCount') {
			setLocalSearchResultCount(arg0);
		} else if (msg.indexOf('markForDownload:') === 0) {
			const s = msg.split(':');
			if (s.length < 2) throw new Error(`Invalid message: ${msg}`);
			void ResourceFetcher.instance().markForDownload(s[1]);
		} else if (msg === 'contextMenu') {
			const resourceId = arg0.resourceId;
			const itemType = await resolveContextMenuItemType(arg0 && arg0.type, resourceId);
			const menu = await contextMenu({
				itemType,
				resourceId: resourceId,
				filename: arg0.filename,
				mime: arg0.mime,
				linkToOpen: null,
				textToCopy: arg0.textToCopy,
				linkToCopy: arg0.linkToCopy || null,
				htmlToCopy: '',
				insertContent: () => { console.warn('insertContent() not implemented'); },
				fireEditorEvent: () => { console.warn('fireEditorEvent() not implemented'); },
				htmlToMd,
				mdToHtml,
			}, dispatch);

			menu.popup({ window: bridge().activeWindow() });
		} else if (msg.indexOf('#') === 0) {
			// This is an internal anchor, which is handled by the WebView so skip this case
		} else if (msg === 'contentScriptExecuteCommand') {
			const commandName = arg0.name;
			const commandArgs = arg0.args || [];
			void CommandService.instance().execute(commandName, ...commandArgs);
		} else if (msg === 'postMessageService.message') {
			void PostMessageService.instance().postMessage({ ...arg0, windowId });
		} else if (msg === 'openPdfViewer') {
			await CommandService.instance().execute('openPdfViewer', arg0.resourceId, arg0.pageNo);
		} else {
			await CommandService.instance().execute('openItem', msg);
			// bridge().showErrorMessageBox(_('Unsupported link or message: %s', msg));
		}
		// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
	}, [dispatch, setLocalSearchResultCount, scrollWhenReadyRef, formNote]);
}
