package org.apache.struts.apps.mailreader.course;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.*;
import org.apache.struts.actions.MappingDispatchAction;
import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
import org.apache.struts.apps.mailreader.dao.User;
import org.apache.struts.apps.mailreader.dao.UserDatabase;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.InvocationTargetException;

/**
 * <p/>
 * Provide an Edit method for retrieving an existing user,
 * and a Save method for updating or inserting a user.
 * </p><p>
 * Both methods utilize a RegistrationForm to obtain or expose User details.
 * If Save is used to create a user,
 * additional validations ensure input is nominal.
 * When a user is created,
 * Save also handles the initial logon.
 * </p>
 */
public class RegisterAction extends MappingDispatchAction {

    // ---- Constants ----

    /**
     * <p/>
     * The application scope attribute under which our user database
     * is stored.
     * </p>
     */
    public static final String DATABASE_KEY = "database";

    /**
     * <p/>
     * Name of fromAddress field ["fromAddress"].
     * </p>
     */
    public final static String FROM_ADDRESS = "fromAddress";

    /**
     * <p/>
     * Name of fullName field ["fullName"].
     * </p>
     */
    public final static String FULL_NAME = "fullName";

    /**
     * <p/>
     * Name of password field ["password"].
     * </p>
     */
    public static String PASSWORD = "password";

    /**
     * <p/>
     * Name of password confirmation field ["password2"].
     * </p>
     */
    public final static String PASSWORD2 = "password2";

    /**
     * <p/>
     * Name of replyToAddress field ["replyToAddress"].
     * </p>
     */
    public final static String REPLY_TO_ADDRESS = "replyToAddress";

    /**
     * <p/>
     * The token representing a "success" result for this application.
     * </p>
     */
    public static final String SUCCESS = "Success";

    /**
     * <p/>
     * The session scope attribute under which the User object
     * for the currently logged in user is stored.
     * </p>
     */
    public static final String USER_KEY = "user";

    /**
     * <p/>
     * Name of username field ["username"].
     * </p>
     */
    public static String USERNAME = "username";

    /**
     * <p/>
     * Name of task field ["task"].
     * </p>
     */
    public final static String TASK = "task";

    // ---- Private Methods ----

    /**
     * <p/>
     * The <code>Log</code> instance for this application.
     * </p>
     */
    private Log log = LogFactory.getLog(Constants.PACKAGE);

    /**
     * <p/>
     * The message prefix to use when populating a Registration Form.
     * </p>
     */
    final String LOG_REGISTRATION_POPULATE = "RegistrationForm.populate";

    /**
     * <p/>
     * Helper method to post error message when user already exists.
     * </p>
     *
     * @param username Existing username
     * @param errors   Our ActionMessages collection
     */
    private void errorUsernameUnique(String username,
                                     ActionMessages errors) {
        errors.add(
                USERNAME,
                new org.apache.struts.action.ActionMessage(
                        "error.username.unique", username));
    }


    /**
     * <p/>
     * Helper method to log event and cancel transaction.
     * </p>
     *
     * @param session Our HttpSession
     * @param method  Method being processed
     * @param key     Attrkibute to remove from session, if any
     */
    private void doCancel(HttpSession session, String method, String key) {
        if (log.isTraceEnabled()) {
            StringBuffer sb = new StringBuffer(128);
            sb.append(Constants.LOG_CANCEL);
            sb.append(method);
            log.trace(sb.toString());
        }
        if (key != null) {
            session.removeAttribute(key);
        }
    }

    /**
     * <p/>
     * Verify input for creating a new user,
     * create the user, and process the login.
     * </p>
     *
     * @param form    The input form
     * @param request The HttpRequest being served
     * @param errors  The ActionMessages collection for any errors
     * @return A new User and empty Errors if create succeeds,
     *         or null and Errors if create fails
     */
    private User doCreateUser(
            ActionForm form,
            HttpServletRequest request,
            ActionMessages errors) {

        if (log.isTraceEnabled()) {
            log.trace(" Perform additional validations on Create");
        }

        UserDatabase database = doGetUserDatabase();
        String username = doGet(form, USERNAME);
        try {
            if (database.findUser(username) != null) {
                errorUsernameUnique(username, errors);
            }
        }
        catch (ExpiredPasswordException e) {
            errorUsernameUnique(username, errors);
            errors.add("errors.literal", new ActionMessage(e.getMessage()));
        }

        String password = doGet(form, PASSWORD);
        if ((password == null) || (password.length() < 1)) {
            errors.add(PASSWORD, new ActionMessage("error.password.required"));

            String password2 = doGet(form, PASSWORD2);
            if ((password2 == null) || (password2.length() < 1)) {
                errors.add(
                        PASSWORD2,
                        new ActionMessage("error.password2.required"));
            }
        }

        if (!errors.isEmpty()) {
            return null;
        }

        User user = database.createUser(username);

        // Log the user in
        HttpSession session = request.getSession();
        session.setAttribute(Constants.USER_KEY, user);
        if (log.isTraceEnabled()) {
            log.trace(
                    " User: '"
                            + user.getUsername()
                            + "' logged on in session: "
                            + session.getId());
        }

        return user;
    }

    /**
     * <p/>
     * Helper method to obtain User form session (if any).
     * </p>
     *
     * @param session Our HttpSession
     * @return User object, or null if there is no user.
     */
    private User doGetUser(HttpSession session) {
        return (User) session.getAttribute(Constants.USER_KEY);
    }

    /**
     * <p/>
     * Confirm user credentials. Post any errors and return User object
     * (or null).
     * </p>
     *
     * @param database Database in which to look up the user
     * @param username Username specified on the logon form
     * @param password Password specified on the logon form
     * @param errors   ActionMessages queue to passback errors
     * @return Validated User object or null
     * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
     *          to be handled by Struts exception
     *          processor via the action-mapping
     */
    private User doGetUser(UserDatabase database, String username,
                           String password, ActionMessages errors)
            throws ExpiredPasswordException {

        User user = null;
        if (database == null) {
            errors.add(
                    ActionMessages.GLOBAL_MESSAGE,
                    new ActionMessage("error.database.missing"));
        } else {

            if (username.equals("Hermes")) {
                throw new ExpiredPasswordException("Hermes");
            }

            user = database.findUser(username);
            if ((user != null) && !user.getPassword().equals(password)) {
                user = null;
            }
            if (user == null) {
                errors.add(
                        ActionMessages.GLOBAL_MESSAGE,
                        new ActionMessage("error.password.mismatch"));
            }
        }

        return user;
    }

    /**
     * <p/>
     * Return a reference to the UserDatabase
     * or null if the database is not available.
     * </p>
     *
     * @return a reference to the UserDatabase or null if the database is not
     *         available
     */
    private UserDatabase doGetUserDatabase() {
        return (UserDatabase) servlet.getServletContext().getAttribute(
                DATABASE_KEY);
    }

    /**
     * <p/>
     * Log a "processing" message for an Action.
     * </p>
     *
     * @param mapping Our ActionMapping
     * @param method  Name of method being processed
     */
    private void doLogProcess(ActionMapping mapping, String method) {
        if (log.isDebugEnabled()) {
            StringBuffer sb = new StringBuffer(128);
            sb.append(" ");
            sb.append(mapping.getPath());
            sb.append(":");
            sb.append(Constants.LOG_PROCESSING);
            sb.append(method);
            log.debug(sb.toString());
        }
    }

    /**
     * <p/>
     * Helper method to populate the input form from the User object.
     * </p>
     *
     * @param form Form with incoming values
     * @param user User object to populate
     * @throws ServletException On any error
     */
    private void doPopulate(ActionForm form, User user)
            throws ServletException {

        final String title = Constants.EDIT;

        if (log.isTraceEnabled()) {
            log.trace(Constants.LOG_POPULATE_FORM + user);
        }

        try {
            PropertyUtils.copyProperties(form, user);
            DynaActionForm dyna = (DynaActionForm) form;
            dyna.set(TASK, title);
            dyna.set(PASSWORD, null);
            dyna.set(PASSWORD2, null);
        } catch (InvocationTargetException e) {
            Throwable t = e.getTargetException();
            if (t == null) {
                t = e;
            }
            log.error(LOG_REGISTRATION_POPULATE, t);
            throw new ServletException(LOG_REGISTRATION_POPULATE, t);
        } catch (Throwable t) {
            log.error(LOG_REGISTRATION_POPULATE, t);
            throw new ServletException(LOG_REGISTRATION_POPULATE, t);
        }
    }

    /**
     * <p/>
     * Helper method to populate the User object from the input form.
     * </p>
     *
     * @param user User object to populate
     * @param form Form with incoming values
     * @throws ServletException On any error
     */
    private void doPopulate(User user, ActionForm form)
            throws ServletException {

        if (log.isTraceEnabled()) {
            log.trace(Constants.LOG_POPULATE_USER + user);
        }

        try {
            String oldPassword = user.getPassword();
            PropertyUtils.copyProperties(user, form);
            String password = doGet(form, PASSWORD);
            if ((password == null)
                    || (password.length() < 1)) {

                user.setPassword(oldPassword);
            }

        } catch (InvocationTargetException e) {
            Throwable t = e.getTargetException();
            if (t == null) {
                t = e;
            }

            log.error(LOG_REGISTRATION_POPULATE, t);
            throw new ServletException(LOG_REGISTRATION_POPULATE, t);

        } catch (Throwable t) {
            log.error(LOG_REGISTRATION_POPULATE, t);
            throw new ServletException(LOG_REGISTRATION_POPULATE, t);
        }
    }

    /**
     * <p/>
     * Helper method to log event and save token.
     * </p>
     *
     * @param request Our HttpServletRequest
     */
    private void doSaveToken(HttpServletRequest request) {
        if (log.isTraceEnabled()) {
            log.trace(Constants.LOG_TOKEN);
        }
        saveToken(request);
    }

    /**
     * <p/>
     * Persist the User object, including subscriptions, to the database.
     * </p>
     *
     * @param user Our User object
     * @throws javax.servlet.ServletException On any error
     */
    private void doSaveUser(User user) throws ServletException {

        final String LOG_DATABASE_SAVE_ERROR =
                " Unexpected error when saving User: ";

        try {
            UserDatabase database = doGetUserDatabase();
            database.save();
        } catch (Exception e) {
            String message = LOG_DATABASE_SAVE_ERROR + user.getUsername();
            log.error(message, e);
            throw new ServletException(message, e);
        }
    }

    /**
     * <p/>
     * Validate and clear the transactional token,
     * creating logging statements as needed.
     * </p>
     *
     * @param request Our HttpServletRequest
     * @param errors  ActionErrors to transfer any messages
     */
    private void doValidateToken(HttpServletRequest request,
                                 ActionMessages errors) {

        if (log.isTraceEnabled()) {
            log.trace(Constants.LOG_TOKEN_CHECK);
        }

        if (!isTokenValid(request)) {
            errors.add(
                    ActionMessages.GLOBAL_MESSAGE,
                    new ActionMessage(Constants.MSG_TRANSACTION_TOKEN));
        }

        resetToken(request);
    }

    // ---- Protected methods ----

    /**
     * <p/>
     * Return the mapping labeled "success"
     * or null if there is no such mapping.
     * </p>
     *
     * @param mapping Our ActionMapping
     * @return Return the mapping named "success" or null if there is no such
     *         mapping.
     */
    protected ActionForward doFindSuccess(ActionMapping mapping) {
        return mapping.findForward(SUCCESS);
    }


    /**
     * <p/>
     * Helper method to fetch a String property from a DynaActionForm.
     * </p>
     * <p/>
     * Values are returned trimmed of leading and trailing whitespace.
     * Zero-length strings are returned as null.
     * </p>
     *
     * @param form     Our DynaActionForm
     * @param property The name of the property
     * @return The value or null if an error occurs
     */
    protected String doGet(ActionForm form, String property) {
        String initial;
        try {
            initial = (String) PropertyUtils.getSimpleProperty(form, property);
        } catch (Throwable t) {
            initial = null;
        }
        String value = null;
        if ((initial != null) && (initial.length() > 0)) {
            value = initial.trim();
            if (value.length() == 0) {
                value = null;
            }
        }
        return value;
    }

    /**
     * <p/>
     * Confirm user credentials. Post any errors and return User object
     * (or null).
     * </p>
     *
     * @param username Username specified on the logon form
     * @param password Password specified on the logon form
     * @param errors   ActionMessages queue to passback errors
     * @return Validated User object or null
     * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
     *          to be handled by Struts exception
     *          processor via the action-mapping
     */
    protected User doGetUser(String username,
                             String password, ActionMessages errors)
            throws ExpiredPasswordException {

        return doGetUser(doGetUserDatabase(), username, password, errors);
    }

    /**
     * <p/>
     * Save any errors and forward to the Input result.
     * </p>
     *
     * @param mapping Our ActionMapping
     * @param request Our HttpServletRequest
     * @param errors  Our ActionMessages collectoin
     * @return The InputForward for this mappintg
     */
    protected ActionForward doInputForward(ActionMapping mapping,
                                           HttpServletRequest request,
                                           ActionMessages errors) {
        this.saveErrors(request, errors);
        return (mapping.getInputForward());
    }

    // ----- Public Methods ----

    /**
     * <p/>
     * Retrieve the User object to edit or null if the User does not exist,
     * and set an transactional token to later detect multiple Save commands.
     * </p>
     *
     * @param mapping  Our ActionMapping
     * @param form     Our ActionForm
     * @param request  Our HttpServletRequest
     * @param response Our HttpServletResponse
     * @return The "Success" result for this mapping
     * @throws Exception on any error
     */
    public ActionForward Edit(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {

        final String method = Constants.EDIT;
        doLogProcess(mapping, method);

        HttpSession session = request.getSession();
        User user = doGetUser(session);
        boolean updating = (user != null);
        if (updating) {
            doPopulate(form, user);
        }

        doSaveToken(request);
        return doFindSuccess(mapping);
    }

    /**
     * <p/>
     * Insert or update a User object to the persistent store.
     * </p><p>
     * If a User is not logged in,
     * then a new User is created and automatically logged in.
     * Otherwise, the existing User is updated.
     * </p>
     *
     * @param mapping  Our ActionMapping
     * @param form     Our ActionForm
     * @param request  Our HttpServletRequest
     * @param response Our HttpServletResponse
     * @return The "Success" result for this mapping
     * @throws Exception on any error
     */
    public ActionForward Save(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {

        final String method = Constants.SAVE;
        doLogProcess(mapping, method);

        HttpSession session = request.getSession();
        if (isCancelled(request)) {
            doCancel(session, method, Constants.SUBSCRIPTION_KEY);
            return doFindSuccess(mapping);
        }

        ActionMessages errors = new ActionMessages();
        doValidateToken(request, errors);

        if (!errors.isEmpty()) {
            return doInputForward(mapping, request, errors);
        }

        User user = doGetUser(session);
        if (user == null) {
            user = doCreateUser(form, request, errors);
            if (!errors.isEmpty()) {
                return doInputForward(mapping, request, errors);
            }
        }

        doPopulate(user, form);
        doSaveUser(user);

        return doFindSuccess(mapping);
    }
}
