import {
	isStringIndexedInterface,
} from "qrc:/js/lib/generated/typeguard";

import {
	assert,
	getKeysOfObject,
	isArray,
	isNumber,
	readSetting,
	writeSetting,
} from "./utils";

export interface CalcSettings {
	baseScaleValues: number[];
}

const defaultCalcSettings: CalcSettings = {
	baseScaleValues: [
		5,
		50,
	],
};

const typeGuardMap: {[key in keyof CalcSettings]: (arg: unknown) => arg is CalcSettings[key]} = {
	baseScaleValues: (arg: unknown) : arg is number[] => isArray(arg, isNumber),
};

function isType<Key extends keyof CalcSettings>(key: Key, arg: unknown): arg is CalcSettings[Key] {
	return typeGuardMap[key](arg);
}

export function isCalcSettings(arg: unknown): arg is CalcSettings {
	return isStringIndexedInterface(arg) && getKeysOfObject(defaultCalcSettings)
		.every(key => isType(key, arg[key]));
}

function isPartialExportSettings(arg: unknown): arg is Partial<CalcSettings> {
	return isStringIndexedInterface(arg) && getKeysOfObject(defaultCalcSettings)
		.every(key => !(key in arg) || isType(key, arg[key]));
}

const settingsKey = "calc_settings";

function updateWithDefaultValue<Key extends keyof CalcSettings>(key: Key, value: Partial<CalcSettings>): Partial<CalcSettings> {
	value[key] = defaultCalcSettings[key];
	return value;
}

export function readCalcSettings(): CalcSettings {
	const incompleteSettings = readSetting(settingsKey, defaultCalcSettings, isPartialExportSettings);
	const completeSettings = getKeysOfObject(defaultCalcSettings)
		.filter(key => !isType(key, incompleteSettings[key]))
		.reduce((acc: Partial<CalcSettings>, key) => updateWithDefaultValue(key, acc), incompleteSettings);
	assert(isCalcSettings(completeSettings), "Expecting complete Export settings");
	return completeSettings;
}

export function writeCalcSettings(value: CalcSettings) : void {
	writeSetting(settingsKey, value);
}
