import {
	isStringIndexedInterface,
} from "qrc:/js/lib/generated/typeguard";
import {
	isInstanceOf,
	isNumber,
	isString,
} from "./utils";

/**
 * Project configuration
 *
 * Note: relevant external API type is [[ProjectConfig]]
 */
export interface ProjectConfigComplete {
	/**
	 * Identifier for a project
	 *
	 * Value is part of the resulting [[GraphRepresentation]]
	 */
	id: string;
}

/**
 * Project configuration
 */
export type ProjectConfig = Partial<ProjectConfigComplete>;

/**
 * ERP-Export configuration
 *
 * Note: relevant external API type is [[ErpExportConfig]]
 */
export interface ErpExportConfigComplete {
	/**
	 * If set, the ERP-Export sends [[GraphRepresentation]] to this url
	 *
	 * The data is sent via a POST request.
	 */
	serverUrl: string;

	/**
	 * If set, the ERP-Export writes [[GraphRepresentation]] to this file
	 */
	filePath: string;

	/**
	 * If set, the article name length is limited to the respective value
	 */
	articleNameMaxLength: number;
}

/**
 * ERP-Export configuration
 */
export type ErpExportConfig = Partial<ErpExportConfigComplete>;

/**
 * Maps script-arg-keys to the respective types
 *
 * Note: this interface is not intended to be instantiated.
 */
export interface ScriptArgs {
	projectConfig: ProjectConfig;
	erpExportConfig: ErpExportConfig;
}

/**
 * Script argument object
 *
 * Example:
 *
 * To submit this [[ProjectConfig]]:
 *
 * ```
 * {
 * 	"id" : "9084290-rev-42"
 * }
 * ```
 *
 * WSi4 needs to be called like this:
 *
 * ```
 * wsi4.exe --script-arg "{\"type\":\"projectConfig\",\"content\":{\"id\":\"9084290-rev-42\"}}"
 * ```
 */
export interface ScriptArg {
	/**
	 * Type of the arg value
	 */
	type: keyof ScriptArgs;

	/**
	 * Content of the arg value
	 *
	 * Note: Union-type is defined by [[type]]
	 */
	content: ProjectConfig|ErpExportConfig;
}

function isProjectConfig(arg: unknown): arg is ProjectConfig {
	return isInstanceOf<ProjectConfig>(arg, {
		id: (arg: unknown) : arg is string | undefined => arg === undefined || isString(arg),
	});
}

function isErpExportConfig(arg: unknown): arg is ErpExportConfig {
	return isInstanceOf<ErpExportConfig>(arg, {
		serverUrl: (arg: unknown) : arg is string | undefined => arg === undefined || isString(arg),
		filePath: (arg: unknown) : arg is string | undefined => arg === undefined || isString(arg),
		articleNameMaxLength: (arg: unknown) : arg is number | undefined => arg === undefined || isNumber(arg),
	});
}

const scriptArgTypeGuardMap: {[index in keyof ScriptArgs]: (arg: unknown) => arg is ScriptArgs[index]} = {
	projectConfig: isProjectConfig,
	erpExportConfig: isErpExportConfig,
};

function isScriptArg<Key extends keyof ScriptArgs>(key: Key, arg: unknown): arg is ScriptArgs[Key] {
	return scriptArgTypeGuardMap[key](arg);
}

export function getScriptArg<Key extends keyof ScriptArgs>(key: Key): ScriptArgs[Key]|undefined {
	for (const arg of wsi4.sharedData.scriptArgs()) {
		const obj = JSON.parse(arg) as unknown;
		if (!isStringIndexedInterface(obj)) {
			continue;
		}
		const type = obj["type"];
		if (type !== key) {
			continue;
		}
		const content = obj["content"];
		if (!isScriptArg(key, content)) {
			continue;
		}
		return content;
	}
	return undefined;
}
