import {
	isBoolean,
	isString,
	readSetting as readSettingImpl,
	writeSetting as writeSettingImpl,
} from "qrc:/js/lib/utils";
import {
	AutomaticProcessConfig,
	isAutomaticProcessConfig,
} from "qrc:/js/lib/graph_post_processing";
import {
	isSheetMaterialUniqueMembers,
} from "qrc:/js/lib/generated/typeguard";
import {
	BendLineEngravingMode,
	isBendLineEngravingMode,
} from "qrc:/js/lib/bend_line_engraving_mode";

/**
 * Settings local to the machine (stored in QSettings)
 *
 * Interface is not intended to be instantiated.
 * Interface can be considered a map that defines available entry keys and the respective types.
 *
 * Note:  Using snake_case as settings keys are potentially case-insensitive.
 */
interface Settings {
	/* eslint-disable camelcase */
	sheet_merging_enabled: boolean;
	automatic_process_config: AutomaticProcessConfig;
	default_sheet_material_id: string | undefined;
	default_bend_line_engraving_mode: BendLineEngravingMode;
	/* eslint-enable camelcase */
}

const typeGuardMap: {[index in keyof Settings]: (arg: unknown) => arg is Settings[index]} = {
	/* eslint-disable camelcase */
	sheet_merging_enabled: isBoolean,
	automatic_process_config: isAutomaticProcessConfig,
	default_sheet_material_id: isString,
	default_bend_line_engraving_mode: isBendLineEngravingMode,
	/* eslint-enable camelcase */
};

const initialValueMap: {[index in keyof Settings]: () => Settings[index]} = {
	/* eslint-disable camelcase */
	// Note:  accessing previously used setting so there is no inconsistent program behaviour
	sheet_merging_enabled: () => readSettingImpl("sheetNodeMergingEnabled", true, isBoolean),
	automatic_process_config: () => ({
		automaticDeburringEnabled: false,
		manualDeburringEnabled: false,
	}),
	// Note:  accessing previously used setting so there is no inconsistent program behaviour
	default_sheet_material_id: () => readSettingImpl("globalMaterial", undefined, isSheetMaterialUniqueMembers)?.identifier,
	default_bend_line_engraving_mode: () => "none",
	/* eslint-enable camelcase */
};

const prefix = "gui_local_settings_";

export function readSetting<Key extends keyof Settings>(key: Key): Settings[Key] {
	return readSettingImpl(
		prefix + key,
		initialValueMap[key](),
		typeGuardMap[key],
	);
}

export function writeSetting<Key extends keyof Settings>(key: Key, value: Settings[Key]): void {
	return writeSettingImpl(prefix + key, value);
}
