package jp.agentec.sinaburocast.action.user;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.mail.MessagingException;

import jp.agentec.sinaburocast.action.AbstractAction;
import jp.agentec.sinaburocast.common.SinaburoConstant;
import jp.agentec.sinaburocast.common.annotation.NoLogin;
import jp.agentec.sinaburocast.common.exception.ExpectedException;
import jp.agentec.sinaburocast.common.exception.InvalidUrlException;
import jp.agentec.sinaburocast.common.exception.SystemException;
import jp.agentec.sinaburocast.common.util.AgtVelocityViewServlet;
import jp.agentec.sinaburocast.common.util.BirthdayUtil;
import jp.agentec.sinaburocast.common.util.PropertyUtil;
import jp.agentec.sinaburocast.common.util.SinaburoUtil;
import jp.agentec.sinaburocast.common.util.SinaburoViewUtil;
import jp.agentec.sinaburocast.entity.Member;
import jp.agentec.sinaburocast.form.user.RegistForm;
import jp.agentec.sinaburocast.logic.MemberRegisterBatchLogic;
import jp.agentec.sinaburocast.service.MemberService;
import jp.agentec.sinaburocast.service.MessageService;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.validator.GenericValidator;
import org.apache.log4j.Logger;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.h2.util.StringUtils;
import org.seasar.framework.util.StringUtil;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;

/**
 * 会員新規登録処理
 *
 * @author kim-hs
 *
 */
@NoLogin
public class RegistAction extends AbstractAction {

	private final Logger logger = Logger.getLogger(getClass());

	public MemberService memberService;
	public MessageService messageService;
	public MemberRegisterBatchLogic memberRegisterBatchLogic;
	
	@Resource
	protected Map requestScope;

	@ActionForm
	public RegistForm registForm;

	/**
	 * 初期表示
	 *
	 * @return
	 * @throws IOException 
	 */
	@Execute(validator = false)
	public String index() throws IOException {
		AgtVelocityViewServlet avvs = new AgtVelocityViewServlet();
		if(avvs.getDevice().equals(SinaburoConstant.AccessType.PC)){
			// PCはトップページを使用する
			redirect("/");
			return null;
		} else {
			return "/user/regist/regist.html";
		}
	}

	/**
	 * 顧客のメールアドレスで
	 * 登録を行う。
	 * メール送信
	 *
	 * @return
	 * @throws IOException 
	 */
	@Execute(validator = false)
	public String regist() throws SystemException, InvalidUrlException , MessagingException, IOException {
		ActionMessages errors = registValidate();
		AgtVelocityViewServlet avvs = new AgtVelocityViewServlet();
		
		if(!errors.isEmpty()){
			request.setAttribute(Globals.ERROR_KEY, errors);
			
			if(avvs.getDevice().equals(SinaburoConstant.AccessType.PC)){
				// PCはトップページを使用する
				return "/";
			} else {
				return "/user/regist/";
			}
		}

		Member member = new Member();

		List<Member> memberList = new ArrayList<Member>();

		if (SinaburoUtil.mobileAddressCheck(registForm.email)) {
			member.mbEmail = registForm.email;
		} else {
			member.pcEmail = registForm.email;
		}

		String id = RandomStringUtils.randomAlphanumeric(6);

		//自動生成のメンバID重複チェック
		while (true) {
			memberList = memberService.findByLoginId(id);
			if (memberList.size() != 0) {
				id = RandomStringUtils.randomAlphanumeric(6);
			} else {
				break;
			}

		}

		member.loginId = id;
		logger.debug(id);
		String pass = RandomStringUtils.randomAlphanumeric(4);
		member.password = pass;
		logger.debug(pass);
		member.validFlg = 1;
		member.pointNum = 0;
		member.authFailNum = 0;
		member.delFlg = 0;
		if(avvs.getDevice().equals(SinaburoConstant.AccessType.PC)){
			member.genderCd = registForm.genderCd;
			member.birthday = registForm.birthdayY + SinaburoUtil.LeftPadZero(registForm.birthdayM, 2) + SinaburoUtil.LeftPadZero(registForm.birthdayD, 2);
		}
		String url3 = PropertyUtil.getString("ENQUETE_SERVER_URL");;

		//メール送信、データ登録
		try {
			int retValue = memberService.insertRegistMailSendLogic(member,registForm.email,url3);
			if(retValue < 1){
				return "/error/500.html";
			}
		} catch (MessagingException e) {
			logger.warn("Mail send failed." + e.toString());
			addErrorMessage("email", SinaburoViewUtil.getMessage("errors.E055"));
			if(avvs.getDevice().equals(SinaburoConstant.AccessType.PC)){
				// PCはトップページを使用する
				return "/";
			} else {
				return "/user/regist/";
			}
		}

		redirect("/user/regist/registEnd");
		return null;

	}
	
	
	/**
	 * 登録完了画面表示
	 *
	 * @return
	 * @throws IOException 
	 */
	@Execute(validator = false)
	public String registEnd() throws IOException {
		return "registEnd.html";
	}

	public ActionMessages registValidate() {
		ActionMessages errors = new ActionMessages();

		// 必須チェック
		if (StringUtil.isBlank(registForm.email)) {
			errors.add("email", new ActionMessage(SinaburoViewUtil.getMessage("errors.required", SinaburoViewUtil.getMessage("labels.contractEmail"))));
		}

		if (StringUtil.isBlank(registForm.email1)) {
			errors.add("email1", new ActionMessage(SinaburoViewUtil.getMessage("errors.required", SinaburoViewUtil.getMessage("labels.contractEmail1"))));
		}

		// エラーがあれば戻す
		if (!errors.isEmpty()) {
			return errors;
		}

		// メール形式チェック「@」が含むかだけチェックする
		if (!registForm.email.matches("^[!-~]+@[!-~]+$")) {
			errors.add("email", new ActionMessage(SinaburoViewUtil.getMessage("errors.email", SinaburoViewUtil.getMessage("labels.contractEmail"))));
		}

		if (!registForm.email1.matches("^[!-~]+@[!-~]+$")) {
			errors.add("email", new ActionMessage(SinaburoViewUtil.getMessage("errors.email", SinaburoViewUtil.getMessage("labels.contractEmail1"))));
		}

		// エラーがあれば戻す
		if (!errors.isEmpty()) {
			return errors;
		}

		// 長さチェック
		if (!GenericValidator.maxLength(registForm.email, 64)) {
			errors.add("email", new ActionMessage(SinaburoViewUtil.getMessage("errors.maxlength", SinaburoViewUtil.getMessage("labels.contractEmail"), "64")));
		}

		if (!GenericValidator.maxLength(registForm.email1, 64)) {
			errors.add("email", new ActionMessage(SinaburoViewUtil.getMessage("errors.maxlength", SinaburoViewUtil.getMessage("labels.contractEmail1"), "64")));
		}

		// エラーがあれば戻す
		if (!errors.isEmpty()) {
			return errors;
		}

		
		// E-mail確認と一致チェック
		if (!StringUtils.equals(registForm.email, registForm.email1)) {
			errors.add("email", new ActionMessage(SinaburoViewUtil.getMessage("errors.E008")));
			return errors;
		}

		// 登録済みのメールアドレスチェック
		Member memberInfo = null;
		if (SinaburoUtil.mobileAddressCheck(registForm.email)) {
			memberInfo = memberService.findByMoEmail(registForm.email);
		} else {
			memberInfo = memberService.findByPcEmail(registForm.email);
		}

		if (memberInfo != null) {
			errors.add("email", new ActionMessage(SinaburoViewUtil.getMessage("errors.E009")));
			return errors;
		}
		
		// PC以外のチェックはここまで
		AgtVelocityViewServlet avvs = new AgtVelocityViewServlet();
		if(!avvs.getDevice().equals(SinaburoConstant.AccessType.PC)){
			// PCはトップページを使用する
			return errors;
		}

		// 誕生日妥当性チェック
		String birthday = registForm.birthdayY + registForm.birthdayM + registForm.birthdayD;

		if (birthday.length() > 0 && birthday.length() < 11) {
			birthday = registForm.birthdayY + SinaburoUtil.LeftPadZero(registForm.birthdayM, 2) + SinaburoUtil.LeftPadZero(registForm.birthdayD, 2);
			SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
			format.setLenient(false);
			try {
				format.parse(birthday);
				// 年齢チェック
				if (BirthdayUtil.isLessAgeRestriction(birthday)) {
					throw new ExpectedException("Less than 16 years old");
				}
			} catch (ParseException e) {
				errors.add("birthdayY", new ActionMessage(SinaburoViewUtil.getMessage("errors.invalid", SinaburoViewUtil.getMessage("labels.birthDay"))));
				return errors;
			} catch (ExpectedException e) {
				errors.add("birthdayY", new ActionMessage(SinaburoViewUtil.getMessage("errors.E054")));
				return errors;
			}
		} else if (birthday.length() == 0) {
			errors.add("birthdayY", new ActionMessage(SinaburoViewUtil.getMessage("errors.required", SinaburoViewUtil.getMessage("labels.birthDay"))));
			return errors;
		}

		return errors;
	}
	
	/**
	 * メールリンクをクリックして会員新規登録処理を行う	
	 * @return
	 * @throws Exception 
	 */
	@Execute(validator = false)
	public String oneClick() {
		try {
			String registerKey = request.getParameter("qUrlId1");
			Member member = memberRegisterBatchLogic.registByKey(registerKey);
			request.setAttribute("member", member);
		} catch (Exception e) {
			if (e instanceof ExpectedException) {
				request.setAttribute("errMsg", SinaburoViewUtil.getMessage(((ExpectedException) e).getCode()));
			}
			else {
				logger.error("oneClick register error. ", e);
				request.setAttribute("errMsg", SinaburoViewUtil.getMessage("errors.E000"));
			}
			return "/error/errorMsg.html";
		}

		return "/user/regist/oneClickRegistEnd.html";
	}

}