// @flow
// basic helpers - common bits of code refactored to DRY
import copy from 'fast-copy';
export { debounce, throttle } from 'throttle-debounce';

// changes a field in an object to a different name
// only required because keys are often mutable
export const changeObjFieldName = (obj: {}, oldName: string, newName: string): {} => {
	return Object.entries(obj)
	.map(([name, val]) => [name === oldName ? newName : name, val])
	.reduce((o, [name, val]) => ({...o, [name]: val}), {});
};

// generates a new unique key given a prefix (like "value" or "param") and possibly conflicting keys
export const generateNewKey = (keyPrefix: string = '', existingKeys: string[]) => {
	if(!existingKeys.includes(keyPrefix))
		return keyPrefix;
	let newKey = '';
	let v = 0;
	while(true) {
		const tryKey = `${ keyPrefix }${ v }`;
		if(existingKeys.includes(tryKey)){
			v++;
			continue;
		}
		newKey = tryKey;
		break;
	}

	return newKey;
};

/*
 * Generates a random "bright" colour, ignoring extreme values (very close to white/black).
 * Adapted from https://stackoverflow.com/a/1484514
 */
export const getRandomBrightColor = () => {
	var letters = '789ABCD';
	var color = '#';
	for (var i = 0; i < 6; i++) {
		color += letters[Math.floor(Math.random() * letters.length)];
	}
	return color;
};

// recursively sorts an object's keys in alphabetical order
// useful for comparing (deeply nested) objects in stringified form.
// probably would be better to use another dep specialized in deeply comparing objects?
export const sortObject = (o: any) => Object.entries(o)
.sort(([n1, v1], [n2, v2]) => n1 > n2 ? 1 : -1)
.reduce((o, [n, v]) => ({...o, [n]: Object((v: any)) === v ? sortObject(v) : v}), {});

export const copyObj = (any: any) => {
	return copy(any);
};

export type GenericObject = {[string]: any};
export type StringObject = {[string]: string};
