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

export type InitialUserDataMode = "none" | "static" | "query";

export function isInitialUserDataMode(arg: unknown): arg is InitialUserDataMode {
	return exhaustiveStringTuple<InitialUserDataMode>()("none", "static", "query").some(mode => mode === arg);
}

/**
 * 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 {
	sheetMergingEnabled: boolean;
	automaticProcessConfig: AutomaticProcessConfig;
	legacyAutomaticProcessConfig: LegacyAutomaticProcessConfig;
	defaultSheetMaterialId: string | undefined;
	defaultTubeMaterialId: string | undefined;
	defaultBendLineEngravingMode: BendLineEngravingMode;
	bendLineEngravingLength: number;
	lstConfigJson: string;
	quotationTemplatePath: string;
	jobCardTemplatePath: string;
	bendDrawingTemplatePath: string;
	lastQuotationExportDir: string;
	initialUserDataValueMode: InitialUserDataMode;
	lastErpJsonExportPath: string;
	sheetUpperSideStrategy: SheetUpperSideStrategy;
}

const typeGuardMap: {[index in keyof Settings]: (arg: unknown) => arg is Settings[index]} = {
	sheetMergingEnabled: isBoolean,
	automaticProcessConfig: isAutomaticProcessConfig,
	legacyAutomaticProcessConfig: isLegacyAutomaticProcessConfig,
	defaultSheetMaterialId: isString,
	defaultTubeMaterialId: isString,
	defaultBendLineEngravingMode: isBendLineEngravingMode,
	bendLineEngravingLength: isNumber,
	lstConfigJson: isString,
	quotationTemplatePath: isString,
	jobCardTemplatePath: isString,
	bendDrawingTemplatePath: isString,
	lastQuotationExportDir: isString,
	initialUserDataValueMode: isInitialUserDataMode,
	lastErpJsonExportPath: isString,
	sheetUpperSideStrategy: isSheetUpperSideStrategy,
};

const initialValueMap: {[index in keyof Settings]: () => Settings[index]} = {
	// Note:  accessing previously used setting so there is no inconsistent program behaviour
	sheetMergingEnabled: () => readSettingImpl("sheetNodeMergingEnabled", true, isBoolean),
	automaticProcessConfig: () => ({}),
	legacyAutomaticProcessConfig: () => ({
		automaticDeburringEnabled: false,
		manualDeburringEnabled: false,
	}),
	// Note:  accessing previously used setting so there is no inconsistent program behaviour
	defaultSheetMaterialId: () => readSettingImpl("globalMaterial", undefined, isSheetMaterialUniqueMembers)?.identifier,
	defaultTubeMaterialId: () => undefined,
	defaultBendLineEngravingMode: () => "none",
	bendLineEngravingLength: () => 0,
	lstConfigJson: () => "",
	quotationTemplatePath: () => "",
	jobCardTemplatePath: () => "",
	bendDrawingTemplatePath: () => "",
	lastQuotationExportDir: () => "",
	initialUserDataValueMode: () => "static",
	lastErpJsonExportPath: () => "",
	sheetUpperSideStrategy: () => "preferConvexity",
};

const prefix = "gui_local_settings_";

const settingsKeyMap = Object.freeze<{[index in keyof Settings]: string}>({
	sheetMergingEnabled: "sheet_merging_enabled",
	automaticProcessConfig: "automatic_process_config_v0",
	legacyAutomaticProcessConfig: "automatic_process_config",
	defaultSheetMaterialId: "default_sheet_material_id",
	defaultTubeMaterialId: "default_tube_material_id",
	defaultBendLineEngravingMode: "default_bend_line_engraving_mode",
	bendLineEngravingLength: "bend_line_engraving_length",
	lstConfigJson: "lst_config_json",
	quotationTemplatePath: "quotation_template_path",
	jobCardTemplatePath: "job_card_template_path",
	bendDrawingTemplatePath: "bend_drawing_template_path",
	lastQuotationExportDir: "last_quotation_export_dir",
	initialUserDataValueMode: "initial_user_data_value_mode",
	lastErpJsonExportPath: "last_erp_json_export_path",
	sheetUpperSideStrategy: "sheet_upper_side_strategy",
});

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

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