const  Registry  = require('rage-edit').Registry;

const SOFTWARE_CLASSES = 'HKCU\\Software\\Classes\\';

export const registerCommand = async options => {
	if (!options) throw new Error('options are empty');

	const { name, icon, command, menu } = options;
	if (!name) throw new Error('name is not specified');
	if (!command) throw new Error('command is not specified');
	if (!menu) throw new Error('menuName is not specified');

	try {
		await Registry.set(`${SOFTWARE_CLASSES}*\\shell\\${name}`);
		await Registry.set(`${SOFTWARE_CLASSES}*\\shell\\${name}`, '', menu);
		if (icon) await Registry.set(`${SOFTWARE_CLASSES}*\\shell\\${name}`, 'Icon', (icon.endsWith('.exe') ? `${icon},0` : icon));
		await Registry.set(`${SOFTWARE_CLASSES}*\\shell\\${name}\\command`, '', `"${command}" "%1"`);
	} catch (e) {
		return Promise.reject(e);
	}

	return Promise.resolve();
};

export const registerDirectoryCommand = async options => {
	if (!options) throw new Error('options are empty');

	const { name, icon, command, menu } = options;
	if (!name) throw new Error('name is not specified');
	if (!command) throw new Error('command is not specified');
	if (!menu) throw new Error('menu is not specified');

	try {
		await Registry.set(`${SOFTWARE_CLASSES}Directory\\shell\\${name}`);
		await Registry.set(`${SOFTWARE_CLASSES}Directory\\shell\\${name}`, '', menu);
		if (icon) await Registry.set(`${SOFTWARE_CLASSES}Directory\\shell\\${name}`, 'Icon', (icon.endsWith('.exe') ? `${icon},0` : icon));
		await Registry.set(`${SOFTWARE_CLASSES}Directory\\shell\\${name}\\command`, '', `"${command}" "%1"`);
	} catch (e) {
		return Promise.reject(e);
	}

	return Promise.resolve();
};

export const registerOpenWithCommand = async (extensions, options) => {
	if (!extensions || !extensions.length) throw new Error('extensions is not specified');
	if (!options) throw new Error('options are empty');

	const { name, command } = options;
	if (!name) throw new Error('name is not specified');
	if (!command) throw new Error('command is not specified');

	try {
		await Promise.all((await findExtensionNames(extensions)).map(async n => {
			await Registry.set(`${SOFTWARE_CLASSES}${n}`);
			await Registry.set(`${SOFTWARE_CLASSES}${n}\\shell\\${name}`);
			await Registry.set(`${SOFTWARE_CLASSES}${n}\\shell\\${name}\\command`, '', `"${command}" "%1"`);
		}));
	} catch (e) {
		return Promise.reject(e);
	}

	return Promise.resolve();
};

export const removeCommand = async name => {
	if (!name) throw new Error('name is not specified');

	try {
		await Registry.delete(`${SOFTWARE_CLASSES}*\\shell\\${name}`);
	} catch (e) {
		return Promise.reject(e);
	}

	return Promise.resolve();
};

export const removeDirectoryCommand = async name => {
	if (!name) throw new Error('name is not specified');

	try {
		await Registry.delete(`${SOFTWARE_CLASSES}Directory\\shell\\${name}`);
	} catch (e) {
		return Promise.reject(e);
	}

	return Promise.resolve();
};

export const removeOpenWithCommand = async (extensions, name) => {
	if (!extensions) throw new Error('extensions is not specified');
	if (!name) throw new Error('name is not specified');

	try {
		await Promise.all((await findExtensionNames(extensions)).map(async n => await Registry.delete(`${SOFTWARE_CLASSES}${n}\\shell\\${name}`)));
	} catch (e) {
		return Promise.reject(e);
	}

	return Promise.resolve();
};

async function findExtensionNames (exts) {
	const { ses_root } = await Registry.get('HKCR');
	return Promise.all(Object.keys(ses_root).filter(e => exts.includes(e)).map(async k => (await Registry.get(`HKCR\\${k}`)).$values['']));
}