export default (context, inject) => {
	const RE_TOKEN_LIST_VALUE = new RegExp(/^(?:\d)+/);
	const RE_TOKEN_NAMED_VALUE = new RegExp(/^(?:\w)+/);

	const isObject = obj => {
		return obj !== null && typeof obj === 'object';
	};

	const parse = msg => {
		let tokens = [];
		let position = 0;

		let text = '';
		while (position < msg.length) {
			let char = msg[position++];
			if (char === '{') {
				if (text) {
					tokens.push({ type: 'text', value: text });
				}

				text = '';
				let sub = '';
				char = msg[position++];
				while (char !== undefined && char !== '}') {
					sub += char;
					char = msg[position++];
				}
				const isClosed = char === '}';

				const type = RE_TOKEN_LIST_VALUE.test(sub)
					? 'list'
					: isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
					? 'named'
					: 'unknown';

				tokens.push({ value: sub, type });
			} else if (char === '%') {
				// when found rails i18n syntax, skip text capture
				if (msg[position] !== '{') {
					text += char;
				}
			} else {
				text += char;
			}
		}
		text && tokens.push({ type: 'text', value: text });

		return tokens;
	};

	const compile = (tokens, values) => {
		const compiled = [];
		let index = 0;
		const mode = Array.isArray(values)
			? 'list'
			: isObject(values)
			? 'named'
			: 'unknown';

		if (mode === 'unknown') {
			return compiled;
		}

		while (index < tokens.length) {
			const token = tokens[index];
			switch (token.type) {
				case 'text':
					compiled.push(token.value);
					break;
				case 'list':
					compiled.push(values[parseInt(token.value, 10)]);
					break;
				case 'named':
					if (mode === 'named') {
						compiled.push(values[token.value]);
					} else {
						if (process.env.NODE_ENV !== 'production') {
							console.log(
								`Type of token '${token.type}' and format of value '${mode}' don't match!`,
							);
						}
					}
					break;
				case 'unknown':
					if (process.env.NODE_ENV !== 'production') {
						console.log("Detect 'unknown' type of token!");
					}
					break;
			}
			index++;
		}

		return compiled;
	};

	const m = (codeId, def, params) => {
		let tokens = [];
		let compiled = [];
		let returnMsg = '';
		let dicList = null,
			userLocale;

		if (context.$auth && context.$auth.user) {
			dicList = context.$auth.user.dicList;
			userLocale = context.$auth.user.user.userLocale;
			returnMsg = dicList[userLocale][codeId];
			if (params) {
				tokens = parse(returnMsg);
				// console.log("tokens: ", tokens);
				compiled = compile(tokens, params);
				// console.log("compiled: ", compiled);
				returnMsg = compiled.join('');
			}
		}

		if (!returnMsg) {
			returnMsg = def;
		}

		return returnMsg;
	};

	inject('m', m);
};
