import {
	isLaserSheetCuttingGasUniqueMembers,
	isSheetMaterialUniqueMembers,
} from "qrc:/js/lib/generated/typeguard";
import {
	exhaustiveStringTuple,
	isArray,
	isBoolean,
	isString,
} from "./utils";

export interface DeducedDataContext {
	workStepType: WorkStepType;
}

/**
 * Note: This interface should never be instantiated.
 * It can be considered a map of available node-DeducedData-entry-keys to the corresponding types
 */
export interface DeducedDataEntries {
	// this member is possibly undefined if the process type of the underlying sheet cutting gas is not `laserSheetCutting`
	laserSheetCuttingGas: LaserSheetCuttingGasUniqueMembers | undefined;
	sheetCuttingProcessId: string;
	// this member can be undefined if sheetFilterSheetIds are not set for any target
	sheetFilterSheetIds: string[]|undefined,
	sheetMaterial: SheetMaterialUniqueMembers | undefined;
	targetsFitOnSheet: boolean;
}

type TypeGuardMap<Entries> = {
	readonly[index in keyof Entries]: (arg: unknown) => arg is Entries[index];
};

const deducedDataTypeGuardMap: TypeGuardMap<DeducedDataEntries> = {
	laserSheetCuttingGas: (arg: unknown): arg is LaserSheetCuttingGasUniqueMembers | undefined => arg === undefined || isLaserSheetCuttingGasUniqueMembers(arg),
	sheetCuttingProcessId: isString,
	sheetFilterSheetIds: (arg: unknown): arg is string[]|undefined => arg === undefined || isArray(arg, isString),
	sheetMaterial: (arg: unknown): arg is SheetMaterialUniqueMembers | undefined => arg === undefined || isSheetMaterialUniqueMembers(arg),
	targetsFitOnSheet: isBoolean,
};

/**
 * @param key Key of the DeducedData entry
 * @param value The value to check
 * @returns True if [[value]] matches the type associated with [[key]]
 */
export function isDeducedDataEntryType<Key extends keyof DeducedDataEntries>(key: Key, value: unknown): value is DeducedDataEntries[Key] {
	return deducedDataTypeGuardMap[key](value);
}

/**
 * @returns Array of DeducedData entry keys
 */
export function deducedDataEntries(): Array<keyof DeducedDataEntries> {
	return exhaustiveStringTuple<keyof DeducedDataEntries>()(
		"sheetMaterial",
		"laserSheetCuttingGas",
		"sheetCuttingProcessId",
		"sheetFilterSheetIds",
		"targetsFitOnSheet",
	);
}
