/*******************************************************************************
 * Copyright 2019 2Fi Business Solutions Ltd.
 *
 * This code is part of the Core project.
 *
 * This code is copyrighted. Under no circumstances should any party, people,
 * or organization should redistribute any portions of this code in any form,
 * either verbatim or through electronic media, to any third parties, unless
 * under explicit written permission by 2Fi Business Solutions Ltd.
 ******************************************************************************/
package com.ffii.core.i18n.support;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.AbstractMessageSource;

import com.ffii.core.dao.JdbcDao;

/**
 * Jdbc MessageSource implementation.
 *
 * <pre>
 * CREATE TABLE `i18n` (
 * 	`locale` varchar(10) NOT NULL,
 * 	`code` varchar(100) NOT NULL,
 * 	`value` varchar(500) DEFAULT NULL,
 * PRIMARY KEY (`locale`,`code`)
 * );
 * </pre>
 *
 * @author Patrick
 */
public class JdbcMessageSource extends AbstractMessageSource {

	@Autowired
	private JdbcDao jdbcDao;

	@Override
	protected String resolveCodeWithoutArguments(String code, Locale locale) {
		return getMessages(locale.toString()).get(code);
	}

	@Override
	protected MessageFormat resolveCode(String code, Locale locale) {
		String msg = getMessages(locale.toString()).get(code);
		return createMessageFormat(msg, locale);
	}

	/** i18n messages cache */
	private static Map<String, Map<String, String>> MESSAGES = new HashMap<String, Map<String, String>>();

	/**
	 * Load a list of messages from i18n table in database
	 *
	 * @param locale
	 *            the locale String (e.g. {@code en_US})
	 */
	public List<Map<String, Object>> loadMessages(String locale) {
		/* prep args */
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("locale", locale);

		/* build sql */
		String sql = "SELECT locale, code, value FROM i18n WHERE locale = :locale";

		/* do query and return */
		return jdbcDao.queryForList(sql, args);
	}

	/**
	 * Get i18n messages map
	 *
	 * @param locale
	 *            the locale String (e.g. {@code en_US})
	 */
	public Map<String, String> getMessages(String locale) {
		Map<String, String> messages = MESSAGES.get(locale);

		/* if not loaded yet, load it from database */
		if (messages == null) {
			messages = new HashMap<String, String>();

			/* convert the list to a simple messages map */
			List<Map<String, Object>> rawMessages = loadMessages(locale);
			for (Map<String, Object> rm : rawMessages) {
				messages.put((String) rm.get("code"), (String) rm.get("value"));
			}

			/* cache the messages */
			MESSAGES.put(locale, messages);
		}

		return messages;
	}

	/**
	 * Reset the i18n messages cache
	 */
	public void resetMessagesCache() {
		/* simply create a new map */
		MESSAGES = new HashMap<String, Map<String, String>>();
	}

}
