package jp.agentec.sinaburocast.helper;

import java.util.Calendar;
import java.util.Date;

import jp.agentec.sinaburocast.common.SinaburoConstant.Formats;
import jp.agentec.sinaburocast.common.exception.ExpectedException;
import jp.agentec.sinaburocast.common.util.EncryptUtil;
import jp.agentec.sinaburocast.common.util.SinaburoUtil;
import jp.agentec.sinaburocast.vo.EmailKey;
import jp.agentec.sinaburocast.vo.EnqueteKey;

import org.apache.log4j.Logger;
import org.seasar.framework.container.annotation.tiger.Component;
import org.seasar.framework.container.annotation.tiger.InstanceType;

@Component(instance = InstanceType.SINGLETON)
public class KeyHelper {
	private final Logger logger = Logger.getLogger(getClass());
	private final static String ENQUETE_MAIL_KEY = "YQe0JrmPqC8A";
	private final static String ENQUETE_ID_KEY = "B7iGNqDv";

	/**
	 * アンケートURL用の暗号化文字列作成
	 * 
	 * @param memberId
	 * @param enqueteId
	 * @param month
	 * @param day
	 * @param hour
	 * @return
	 * @throws Exception
	 */
	public String encrypt(Integer memberId, Integer enqueteId, int month, int day, int hour) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, month);
		cal.add(Calendar.DAY_OF_MONTH, day);
		cal.add(Calendar.HOUR_OF_DAY, hour);
		return encrypt(memberId, enqueteId, cal.getTime());
	}

	/**
	 * メンバーID, アンケートID, 有効期限を暗号化した文字列を返す。
	 * URLに使用される+/=はそれぞれ-_@に置換する。
	 * 
	 * @param memberId
	 * @param enqueteId
	 * @param expired
	 * @return
	 * @throws Exception
	 */
	public String encrypt(Integer memberId, Integer enqueteId, Date expired) throws Exception {
		String dateTime = SinaburoUtil.convertTimestampToString(expired, Formats.DATE_TIME);
		String orgVal = memberId + "," + enqueteId + "," + dateTime;
		String encVal = EncryptUtil.encryptBASE64(ENQUETE_MAIL_KEY, orgVal);
		return encVal.replace("+", "-").replace("/", "_").replace("=", "@");
	}

	/**
	 * 文字列を復号化し、メンバーID, アンケートID, 有効期限を含むオブジェクトを返す。
	 * 
	 * @param encryptStr
	 * @return
	 * @throws Exception
	 */
	public EnqueteKey decrypt(String encryptStr) throws Exception {
		if (encryptStr == null) {
			throw new ExpectedException("argument is null");
		}
		try {
			String orgVal = EncryptUtil.decryptBASE64(ENQUETE_MAIL_KEY, encryptStr.replace("-", "+").replace("_", "/").replace("@", "="));
			return new EnqueteKey(orgVal);
		} catch (Exception e) {
			logger.error("Decrypt failed. " + e.toString());
			throw new ExpectedException("Invalid String");
		}
	}

	/**
	 * ユーザ登録用の暗号化文字列作成
	 * 
	 * @param email
	 * @param month
	 * @param day
	 * @param hour
	 * @return
	 * @throws Exception
	 */
	public String encryptEmail(String email, int month, int day, int hour) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, month);
		cal.add(Calendar.DAY_OF_MONTH, day);
		cal.add(Calendar.HOUR_OF_DAY, hour);
		return encryptEmail(email, cal.getTime());
	}

	/**
	 * メンバーID, アンケートID, 有効期限を暗号化した文字列を返す。
	 * URLに使用される+/はそれぞれ-_に置換する。
	 * 末尾の==は除去
	 * 
	 * @param memberId
	 * @param enqueteId
	 * @param expired
	 * @return
	 * @throws Exception
	 */
	public String encryptEmail(String email, Date expired) throws Exception {
		String dateTime = SinaburoUtil.convertTimestampToString(expired, Formats.DATE_TIME);
		String orgVal = email + "," + dateTime;
		String encVal = EncryptUtil.encryptBASE64(ENQUETE_MAIL_KEY, orgVal);
		return encVal.replace("+", "-").replace("/", "_").replace("=", "!");
	}

	/**
	 * 文字列を復号化し、メンバーID, アンケートID, 有効期限を含むオブジェクトを返す。
	 * 
	 * @param encryptStr
	 * @return
	 * @throws Exception
	 */
	public EmailKey decryptEmail(String encryptStr) throws Exception {
		if (encryptStr == null) {
			throw new ExpectedException("argument is null");
		}
		try {
			String orgVal = EncryptUtil.decryptBASE64(ENQUETE_MAIL_KEY, encryptStr.replace("-", "+").replace("_", "/").replace("!", "="));
			return new EmailKey(orgVal);
		} catch (Exception e) {
			logger.error("Decrypt failed. " + e.toString());
			throw new ExpectedException("Invalid String");
		}
	}

	public String encryptEnqueteId(Integer enqueteId) throws Exception {
		return EncryptUtil.encryptBASE64(ENQUETE_ID_KEY, "" + enqueteId);
	}

	public String decryptEnqueteId(String encryptStr) throws Exception {
		return EncryptUtil.decryptBASE64(ENQUETE_ID_KEY, encryptStr);
	}
}