import { v4 as uuid} from 'uuid';

import { themeProps, Theme } from './theme';

export type Default = null;
export type Color = string;
export type FuncName = 'alpha' | 'darken' | 'lighten';
export type Func = { type: 'func'; name: FuncName; arg: number; value: string; };
export type RefProp = { type: 'refProp'; key: string; };
export type RefConst = { type: 'refConst'; key: string; };
export type Css = { type: 'css'; value: string; };

export type ThemeValue = Color | Func | RefProp | RefConst | Css | Default;

export type ThemeViewModel = [ string, ThemeValue ][];

export const fromThemeString = (str?: string) : ThemeValue => {
	if (!str) return null;
	if (str.startsWith(':')) {
		const parts = str.slice(1).split('<');
		const name = parts[0] as FuncName;
		const arg = parseFloat(parts[1]);
		const value = parts[2].startsWith('@') ? parts[2].slice(1) : '';
		return { type: 'func', name, arg, value };
	} else if (str.startsWith('@')) {
		return {
			type: 'refProp',
			key: str.slice(1),
		};
	} else if (str.startsWith('$')) {
		return {
			type: 'refConst',
			key: str.slice(1),
		};
	} else if (str.startsWith('"')) {
		return {
			type: 'css',
			value: str.substr(1).trim(),
		};
	} else {
		return str;
	}
};

export const toThemeString = (value: Color | Func | RefProp | RefConst | Css) => {
	if (typeof value === 'string') return value;
	switch (value.type) {
		case 'func': return `:${value.name}<${value.arg}<@${value.value}`;
		case 'refProp': return `@${value.key}`;
		case 'refConst': return `$${value.key}`;
		case 'css': return `" ${value.value}`;
	}
};

export const convertToMisskeyTheme = (vm: ThemeViewModel, name: string, desc: string, author: string, base: 'dark' | 'light'): Theme => {
	const props = { } as { [key: string]: string };
	for (const [ key, value ] of vm) {
		if (value === null) continue;
		props[key] = toThemeString(value);
	}

	return {
		id: uuid(),
		name, desc, author, props, base
	};
};

export const convertToViewModel = (theme: Theme): ThemeViewModel => {
	const vm: ThemeViewModel = [];
	// プロパティの登録
	vm.push(...themeProps.map(key => [ key, fromThemeString(theme.props[key])] as [ string, ThemeValue ]));

	// 定数の登録
	const consts = Object
		.keys(theme.props)
		.filter(k => k.startsWith('$'))
		.map(k => [ k, fromThemeString(theme.props[k]) ] as [ string, ThemeValue ]);

		vm.push(...consts);
	return vm;
};
