import FMProxy from './fm-proxy'
import {FMPromise} from "./fm-promise";
import {ScriptOptions} from "./types";


declare global {
	interface Window {
		webViewerName: string,
		fmPromise: FMPromise,
		$FMP_WEB_VIEWER_NAME: string
	}
}

/**
 * The default <code>webViewerName</code> is "fmPromiseWebViewer". This corresponds to the webViewer layout object by FileMaker to call back into JavaScript.
 * @param s:string
 */
window.webViewerName = window.$FMP_WEB_VIEWER_NAME || new URLSearchParams(window.location.search).get('webViewerName') || 'fmPromiseWebViewer';

window.fmPromise = new FMPromise();

/**
 * Performs a FileMaker script, returning a Promise.
 * The promise will be rejected if the FileMaker script result starts with the word "ERROR".
 * <p>
 * The Promise will be resolved with parsed JSON if possible, unless `options.alwaysReturnString` is `true`.
 * <p>
 * You can specify `options.runningScript` to control how currently running FileMaker script is handled. 0:continue, 1:halt, 2:exit, 3:Resume, 4:Pause, 5:Interrupt.
 * See https://filemakersupport.force.com/en/s/article/FileMaker-Pro-19-1-2-Updater-Release-Notes
 * @return {Promise} which will be resolved / rejected by the `scriptName` being called
 * @param scriptName{string} FileMaker script to perform
 * @param scriptParameter optional parameter to pass to the script
 * @param options
 */
const PerformScript = (scriptName: string, scriptParameter: any = null, options: ScriptOptions = {runningScript: 0, alwaysReturnString: false}):Promise<any> => {
	if (scriptParameter && typeof scriptParameter !== 'string') {
		scriptParameter = JSON.stringify(scriptParameter);
	}
	const option = options?.runningScript || 0;
	const promiseId = (Math.random() + 1).toString(36).substring(7);
	return FMProxy
		.then((fm) => {
			return new Promise((resolve: (any), reject: (any)) => {
				const webViewerName = window.webViewerName; // get this as late as possible, in case it has changed
				const meta = JSON.stringify({scriptName, promiseId, webViewerName});
				window.fmPromise.registerPromise(promiseId, {resolve, reject});
				console.info(promiseId + ' Performing script', scriptName, 'with param', scriptParameter);
				const comboParam = meta + '\n' + scriptParameter;
				if (option === 0) { // use PerformScript for backwards compatibility prior to FileMaker 9.1.2
					fm.PerformScript('fmPromise', comboParam);
				} else {
					fm.PerformScriptWithOption('fmPromise', comboParam, option);
				}
			})
		})
		.then((result) => { // try parsing FM result if it looks like JSON
			if (!options?.alwaysReturnString && result && typeof result === 'string' && (result[0] === '{' || result[0] === '[')) {
				try {
					result = JSON.parse(result);
				} catch (e) {
					console.warn('Unable to parse JSON result ', result, e);
				}
			}
			return result;
		});
}

export default PerformScript;
