/**
 * <p>
 * Copyright © 2009-2010, Res Interactive, LLC
 * </p>
 * <p>
 * Based upon public domain sample code provided by Authorize.net
 * </p>
 * <p>
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * </p>
 * <p>
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * </p>
 * <p>
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * </p>
 * 
 * @author brpocock
 */
package org.starhope.appius.mb;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.naming.NamingException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.starhope.appius.except.*;
import org.starhope.appius.game.AppiusClaudiusCaecus;
import org.starhope.appius.messaging.Mail;
import org.starhope.appius.pay.util.CredentialType;
import org.starhope.appius.pay.util.PaymentCredential;
import org.starhope.appius.types.AgeBracket;
import org.starhope.appius.user.Parent;
import org.starhope.appius.user.User;

import com.tootsville.WebUtil;
import com.tootsville.user.Toot;

/**
 * TODO: The documentation for this type (IBCRegister) is incomplete.
 * (brpocock, Sep 23, 2009)
 * 
 * @author brpocock
 */
@Deprecated
public class IBCRegister {

	/**
	 * TODO: document this method (brpocock, Sep 23, 2009)
	 * 
	 * @param ibcCode WRITEME
	 * @return WRITEME
	 * @throws NotImplementedException WRITEME
	 */
	public static boolean verifyCodeNumber (final String ibcCode)
	throws NotImplementedException {
		try {
			PaymentCredential.verifyIBC (ibcCode);
		} catch (final AlreadyUsedException e) {
			return false;
		} catch (final NotFoundException e) {
			return false;
		}
		return true;
	}

	/**
	 * TODO: document this member (brpocock, Sep 23, 2009)
	 */
	private String ibcCode = "";

	/**
	 * TODO: document this member (brpocock, Sep 23, 2009)
	 */
	private int months = 0;
	/**
	 * TODO: document this member (brpocock, Sep 23, 2009)
	 */
	private Parent parent = null;

	/**
	 * TODO: document this member (brpocock, Sep 23, 2009)
	 */
	private String toot = "moo";

	/**
	 * TODO: document this member (brpocock, Sep 23, 2009)
	 */
	private User user = null;

	/**
	 * @param newIBCCode WRITEME
	 * @throws NotFoundException WRITEME
	 * @throws AlreadyUsedException WRITEME
	 * @throws NotImplementedException WRITEME
	 */
	public IBCRegister (final String newIBCCode)
	throws NotFoundException, AlreadyUsedException,
	NotImplementedException {
		ibcCode = newIBCCode;
		setMonths (PaymentCredential.verifyIBC (newIBCCode));
	}

	/**
	 * TODO: document this method (theys, Sep 18, 2009)
	 * 
	 * @param newUser WRITEME
	 * @throws NotImplementedException WRITEME
	 */
	public void applyIBC (final User newUser)
	throws NotImplementedException {
		final PaymentCredential credentials = new PaymentCredential ();
		credentials.setIBCCard (ibcCode);
		credentials.setCredentialType (CredentialType.IBC_CARD);
	}

	/**
	 * Don't use this method, it may yield unexpected results.
	 * 
	 * @param request WRITEME
	 * @param storeValues WRITEME
	 * @param session WRITEME
	 * @param err WRITEME
	 * @param suc WRITEME
	 * @return WRITEME
	 */
	@Deprecated
	public String createUser (final ServletRequest request,
			final Map <String, String> storeValues,
			final HttpSession session, final Map <String, String> err,
			final Map <String, String> suc) {

		for (final String param : new String [] { "year", "month",
				"day", "username", "password", "passwordConfirm",
				"securityQuestion", "securityAnswer" }) {
			storeValues.put (param, request.getParameter (param));
		}

		session.setAttribute ("storeValues", storeValues);

		final String registerUsername = request
		.getParameter ("username");
		final String registerPassword = request
		.getParameter ("password");
		final String confirmPassword = request
		.getParameter ("passwordConfirm");
		final String question = request
		.getParameter ("securityQuestion");
		final String answer = request.getParameter ("securityAnswer");

		final String month = request.getParameter ("month");
		final String day = request.getParameter ("day");
		final String year = request.getParameter ("year");

		// Create a string in JDBC timestamp format: yyyy-mm-dd
		final String date = year + "-" + month + "-" + day;

		java.sql.Date dob = null;
		System.err.println ("A user is registering. Username: "
				+ registerUsername + " DOB: " + date + ".");

		System.err.println (storeValues.toString ());
		boolean isAllGood = true;
		if (null != registerUsername && null != registerPassword
				&& null != confirmPassword && null != question
				&& null != answer && registerPassword.length () != 0
				&& date.length () != 0
				&& confirmPassword.length () != 0
				&& question.length () != 0 && answer.length () != 0) {

			try {
				dob = java.sql.Date.valueOf (date);
			} catch (final IllegalArgumentException e) {
				err.put ("dob", Messages.dob_invalid ());
				System.err.println ("We have toots from future!");
				isAllGood = false;
			}

			if (null == request.getParameter ("agree")) {
				err.put ("agree", Messages.getText ("agree_ts_and_cs"));
				System.err
				.println ("Uh oh!  Someone jacked up their registration.");
				isAllGood = false;
			}

			if (null != dob && dob.after (new java.util.Date ())) {
				err.put ("dob", Messages.dob_invalid ());
				System.err.println ("We have toots from the future!");
				isAllGood = false;
			}

			if ( !registerPassword.equals (confirmPassword)) {
				err.put ("password", Messages
						.getText ("password_mismatch"));
				System.err
				.println ("Password does not match confirmation");
				isAllGood = false;
			}

			if (registerPassword.length () < User.MIN_PW_LENGTH) {
				err.put ("password", Messages
						.getText ("password_length"));
				System.err.println ("Password too short");
				isAllGood = false;
			}

			if (registerUsername.length () < User.MIN_LOGIN_LENGTH) {
				err.put ("username", Messages.getText ("login_length"));
				System.err.println ("Login name too short");
				isAllGood = false;
			}

			System.err.println (isAllGood);

			if (isAllGood) {
				// Create new user account
				try {
					user = User.create (dob, toot
							.toLowerCase (Locale.ENGLISH),
							registerUsername);

					user.setPassword (registerPassword);
					user.setPasswordRecovery (question, answer);

					if (null != request.getParameter ("code")
							&& !request.getParameter ("code").equals (
							"")) {
						System.err.println ("nut code: "
								+ request.getParameter ("code"));
						System.out.println ("checking peanut code");
						String pnt = "";
						try {
							if (user instanceof Toot) {
								pnt = ((Toot) user)
								.acceptPeanutCode (request
										.getParameter ("code"));
							}
						} catch (final NotFoundException e) {
							System.err
							.println ("Someone entered an invalid peanut code");
							err.put ("code", Messages.code_invalid ());
						} catch (final AlreadyUsedException e) {
							System.err
							.println ("Someone entered an invalid peanut code");
							err.put ("code", Messages.code_invalid ());
						}
						suc.put ("", pnt);
					}

					// If a user is registering, log them in
					session.setAttribute ("sUserID", user.getUserID ());
					session.setAttribute ("sUserType", WebUtil.USER);
					session.setAttribute ("sUserPassword",
							registerPassword);
					System.err
					.println (user.getDisplayName ()
							+ " has completed registering themself.  Let's welcome "
							+ user.getDisplayName ());// Redirect
					return "/ibc/email/";

				} catch (final AlreadyUsedException e) {
					err.put ("username", Messages
							.getText ("username_unavail"));
					session.setAttribute ("sError", err);
				} catch (final ForbiddenUserException e) {
					err.put ("username", Messages
							.getText ("username_unavail"));
					session.setAttribute ("sError", err);
				}
			}
		} else {
			if (null == registerUsername
					|| registerUsername.length () == 0) {
				err.put ("username", Messages.blank_field ("username"));
			}
			if (null == registerPassword
					|| registerPassword.length () == 0) {
				err.put ("password", Messages.blank_field ("password"));
			}
			if (date.length () == 0) {
				err.put ("dob", Messages.blank_field ("date of birth"));
			}
			if (null == confirmPassword
					|| confirmPassword.length () == 0) {
				err.put ("passwordConfirm", Messages
						.blank_field ("password confirmation"));
			}
			if (null == answer || answer.length () == 0) {
				err.put ("answer", Messages
						.blank_field ("forgotten password answer"));
			}
		}

		if (err.size () > 0) {
			/**
			 * If there was any errors caught, return to last page with
			 * the error message.
			 */
			session.setAttribute ("sError", err);

			return "/membership/register/user-details/";
		}

		return "/membership/";

	}

	/**
	 * TODO: document this method (brpocock, Sep 12, 2009)
	 * 
	 * @param request WRITEME
	 * @param storeValues WRITEME
	 * @param session WRITEME
	 * @param err WRITEME
	 * @return WRITEME
	 */
	public String fromMail (final HttpServletRequest request,
			final HashMap <String, String> storeValues,
			final HttpSession session,
			final HashMap <String, String> err) {
		if (null != request.getParameter ("email")
				&& !request.getParameter ("email").equals ("")
				&& null != request.getParameter ("emailConfirm")
				&& !request.getParameter ("emailConfirm").equals ("")) {

			final String registerEmail = request.getParameter ("email");
			final String confirmEmail = request
			.getParameter ("emailConfirm");
			final Integer userID = (Integer) session
			.getAttribute ("sUserID");

			System.err.println ("New user's email: " + registerEmail
					+ "  new user's confirmation: " + confirmEmail);

			if (null == user) {
				err
				.put ("username", Messages
						.getText ("login_invalid"));
				System.err
				.println ("User:  ("
						+ userID
						+ ") failed to set up their email.  They have timed out.");
				session.setAttribute ("sError", err);
				return "/membership/";
			}
			System.err.println ("User:  (" + userID
					+ ") has been identified as "
					+ user.getDisplayName ());
			try {
				Mail.validateMail (registerEmail);
			} catch (final DataException e) {
				// Default catch action, report bug
				// (brpocock, Sep 11, 2009)
				AppiusClaudiusCaecus.reportBug (e);
			} catch (final NamingException e) {
				// Default catch action, report bug
				// (brpocock, Sep 11, 2009)
				AppiusClaudiusCaecus.reportBug (e);
			}
			if (registerEmail.equals (confirmEmail)) {
				if (AgeBracket.Kid == user.getAgeGroup ()) {
					final Parent sessionParent = Parent
					.getOrCreateByMail (registerEmail);
					try {
						user.setParent (sessionParent);
					} catch (final GameLogicException e) {
						// Default catch action, report bug
						// (brpocock, Sep 11, 2009)
						AppiusClaudiusCaecus.reportBug (e);
					} catch (final ForbiddenUserException e) {
						// Default catch action, report bug
						// (brpocock, Sep 11, 2009)
						AppiusClaudiusCaecus.reportBug (e);
					}
					sessionParent.sendNotificationForChild (user);
					return "/membership/register/congrats/?who=chase";
				}
				try {
					user.setMail (registerEmail);
				} catch (final GameLogicException e) {
					// Default catch action, report bug
					// (brpocock, Sep 11, 2009)
					AppiusClaudiusCaecus.reportBug (e);
				}
				if (null != request.getParameter ("canContact")) {
					user.setCanContact (true);
					System.err.println (user.getDisplayName ()
							+ " has agreed to receive promotions.");
				}
				return "/membership/register/congrats/?who=chase";
			}
			err.put ("email", Messages.getText ("mail_mismatch"));

		} else {
			err.put ("username", Messages.getText ("mail_invalid"));
		}

		if (err.size () > 0) {
			/**
			 * If there was any errors caught, return to last page with
			 * the error message.
			 */
			session.setAttribute ("sError", err);
			System.err
			.println ("Uh oh!  A parent jacked up their registration.");
			return "/membership/register/email/";
		}
		return "/membership/"; // default fall-back
	}

	/**
	 * TODO: document this method (brpocock, Sep 24, 2009)
	 * 
	 * @return WRITEME
	 */
	public int getMonths () {
		// default getter (theys, Sep 17, 2009)
		return months;
	}

	/**
	 * TODO: document this method (brpocock, Sep 24, 2009)
	 * 
	 * @return WRITEME
	 */
	public String getToot () {
		// default getter (theys, Sep 17, 2009)
		return toot;
	}

	/**
	 * TODO: document this method (brpocock, Sep 24, 2009)
	 */
	public void ibcTransact () {
		if (null == user) {
			// TODO
		}
	}

	/**
	 * TODO: document this method (brpocock, Sep 23, 2009)
	 * 
	 * @param months1 WRITEME
	 */
	private void setMonths (final int months1) {
		// default setter (theys, Sep 17, 2009)
		months = months1;
	}

	/**
	 * TODO: document this method (brpocock, Sep 23, 2009)
	 * 
	 * @param toot1 WRITEME
	 */
	public void setToot (final String toot1) {
		// default setter (theys, Sep 17, 2009)
		toot = toot1;
	}

	/**
	 * TODO: document this method (brpocock, Sep 23, 2009)
	 * 
	 * @param email WRITEME
	 * @throws GameLogicException WRITEME
	 * @throws ForbiddenUserException WRITEME
	 */
	public void setUserEmail (final String email)
	throws GameLogicException, ForbiddenUserException {
		if (null != user) {
			if (AgeBracket.Kid == user.getAgeGroup ()) {
				user.setMail (email);
			} else {
				parent = Parent.getOrCreateByMail (email);
				user.setParent (parent);
			}
		}
	}
}
