import fs from 'fs';
import { i18nMap } from './i18nMap';
import { KeyParams } from './KeyParams';

class i18nLoader {
	private static instance: i18nLoader;
	private readonly map: i18nMap;
	private locale: string;
	public static defaultLocale = 'en_US';
	public constructor(locale: string) {
		this.locale = locale;
		this.map = <i18nMap>{
			'en_US': {
				'org.crazydoctor.expressts.start': 'org.crazydoctor.expressts server started on port {port}',
				'org.crazydoctor.expressts.httpError.500': 'Internal server error',
				'org.crazydoctor.expressts.httpError.404': 'Page {url} not found',
				'org.crazydoctor.expressts.swagger.registered': 'Swagger documentation is available on {path}',
				'org.crazydoctor.expressts.swagger.routeGenerated': 'Swagger documentation for route \'{route}\' generated'
			}
		};
	}

	public static getInstance(locale?: string): i18nLoader {
		if(!i18nLoader.instance)
			i18nLoader.instance = new i18nLoader(locale ?? i18nLoader.defaultLocale);
		return i18nLoader.instance;
	}

	public setLocale(locale: string): i18nLoader {
		this.locale = locale;
		return this;
	}

	public load(...paths: string[]): i18nLoader {
		for(const p of paths) {
			try {
				const data = fs.readFileSync(p).toString('utf8');
				try {
					this.loadJson(<i18nMap>JSON.parse(data));
				} catch (err) {
					console.error('JSON parsing error:', err);
				}
			} catch(error) {
				console.error(`i18n file '${p}' not found.`, error);
			}
		}
		return this;
	}

	public loadJson(obj: i18nMap): i18nLoader {
		for(const locale of Object.keys(obj)) {
			if(!this.map[<string>locale]) this.map[locale] = {};
			for(const key of Object.keys(obj[locale]))
				this.map[locale][key] = obj[locale][key];
		}
		return this;
	}

	public get(key: string): string {
		let value;

		if(!this.map[this.locale] && !this.map[i18nLoader.defaultLocale])
			return key;

		if(this.map[i18nLoader.defaultLocale])
			value = this.map[i18nLoader.defaultLocale][key];

		if(this.map[this.locale])
			value = this.map[this.locale][key] ?? value;

		return value ?? key;
	}
}

const $$ = (key: string, params?: KeyParams): string => {
	let text = i18nLoader.getInstance().get(key);

	if(params) {
		for(const param of Object.keys(params)) {
			const regex = new RegExp(`\{${param}\}`, 'g');
			text = text.replace(regex, params[param]);
		}
	}

	return text;
};

export { i18nLoader, $$ };