package org.appfuse.webapp.action;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.LabelValueBean;
import org.apache.struts.util.MessageResources;
import org.apache.struts.util.RequestUtils;
import org.appfuse.Constants;
import org.appfuse.model.User;
import org.appfuse.model.UserRole;
import org.appfuse.service.UserManager;
import org.appfuse.util.MailUtil;
import org.appfuse.util.StringUtil;
import org.appfuse.webapp.form.UserForm;
import org.appfuse.webapp.form.UserFormEx;
import org.appfuse.webapp.util.RequestUtil;
public final class UserAction extends BaseAction {
    
    private static Log log = LogFactory.getLog(UserAction.class);
    public ActionForward add(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'add' method");
        }
                        getMessages(request);
        ArrayList roles = new ArrayList();
                roles.add(new LabelValueBean(Constants.USER_ROLE, Constants.USER_ROLE));
                request.setAttribute(Constants.USER_ROLES, roles);
        return mapping.findForward("edit");
    }
    public ActionForward cancel(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'cancel' method");
        }
        if (!StringUtils.equals(request.getParameter("from"), "list")) {
            return mapping.findForward("mainMenu");
        } else {
            return mapping.findForward("viewUsers");
        }
    }
    public ActionForward delete(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'delete' method");
        }
        
        UserForm userForm = (UserForm) form;
                UserManager mgr = (UserManager) getBean("userManager");
        mgr.removeUser(convert(userForm));
        ActionMessages messages = new ActionMessages();
        messages.add(ActionMessages.GLOBAL_MESSAGE,
            new ActionMessage("user.deleted", userForm.getUsername()));
        saveMessages(request, messages);
                return mapping.findForward("viewUsers");
    }
    public ActionForward edit(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'edit' method");
        }
        UserForm userForm = (UserForm) form;
        HttpSession session = request.getSession();
                if (request.getRequestURL().indexOf("editProfile") > -1) {
                                                if ((request.getParameter("username") != null) ||
                    (request.getParameter("from") != null)) {
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
                log.warn("User '" + request.getRemoteUser() +
                         "' is trying to edit user '" +
                         request.getParameter("username") + "'");
                return null;
            }
        }
                UserManager mgr = (UserManager) getBean("userManager");
        User user = null;
                if (request.getParameter("username") != null) {
                        user = (User) mgr.getUser(userForm.getUsername());
        } else {
                        user =
                (User) mgr.getUser(getUser(session).getUsername());
        }
        UserFormEx ex = new UserFormEx();
        BeanUtils.copyProperties(ex, convert(user));
        ex.setConfirmPassword(ex.getPassword());
        request.setAttribute(Constants.USER_EDIT_KEY, ex);
        setupRoles(user, request);
                        if (log.isDebugEnabled()) {
            log.debug("checking for cookieLogin...");
        }
        if (session.getAttribute("cookieLogin") != null) {
            ActionMessages messages = new ActionMessages();
                        messages.add(ActionMessages.GLOBAL_MESSAGE,
                         new ActionMessage("userProfile.cookieLogin"));
            saveMessages(request, messages);
        }
                return mapping.findForward("edit");
    }
    public ActionForward save(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'save' method");
        }
                ActionErrors errors = new ActionErrors();
        ActionMessages messages = new ActionMessages();
        UserFormEx userForm = (UserFormEx) form;
        String password = userForm.getPassword();
        User user = new User();
                        BeanUtils.copyProperties(user, userForm);
        if (StringUtils.equals(request.getParameter("encryptPass"), "true")) {
            String algorithm = (String) servlet.getServletContext()
                                               .getAttribute(Constants.ENC_ALGORITHM);
            if (algorithm == null) {                 log.debug("assuming testcase, setting algorigthm to 'SHA'");
                algorithm = "SHA";
            }
            user.setPassword(StringUtil.encodePassword(password, algorithm));
        }
        UserManager mgr = (UserManager) getBean("userManager");
        try {
            user = (User) mgr.saveUser(user);
            setupRoles(user, request);
        } catch (Exception e) {
            if ((e.getMessage() != null) &&
                    (e.getMessage().indexOf("Duplicate entry") != -1)) {
                                log.warn("User already exists: " + e.getMessage());
                errors.add(ActionErrors.GLOBAL_ERROR,
                    new ActionError("errors.existing.user",
                        userForm.getUsername(), userForm.getEmail()));
                saveErrors(request, errors);
                return mapping.findForward("edit");
            }
            e.printStackTrace();
            errors.add(ActionErrors.GLOBAL_ERROR,
                new ActionError("errors.general"));
            while (e != null) {
                errors.add(ActionErrors.GLOBAL_ERROR,
                    new ActionError("errors.detail", e.getMessage()));
                e = (Exception) e.getCause();
            }
            saveErrors(request, errors);            
            return mapping.findForward("edit");
        }
        HttpSession session = request.getSession();
        if (!StringUtils.equals(request.getParameter("from"), "list")) {
            session.setAttribute(Constants.USER_KEY, user);
                                    if ((RequestUtil.getCookie(request, Constants.LOGIN_COOKIE) != null) &&
                    (session.getAttribute("cookieLogin") == null)) {
                                mgr.removeLoginCookies(userForm.getUsername());
                String autoLogin =
                    mgr.createLoginCookie(userForm.getUsername());
                RequestUtil.setCookie(response, Constants.LOGIN_COOKIE,
                                      autoLogin, request.getContextPath());
            }
                        messages.add(ActionMessages.GLOBAL_MESSAGE,
                new ActionMessage("user.updated"));
            session.setAttribute(Globals.MESSAGE_KEY, messages);
                        return mapping.findForward("mainMenu");
        } else {
                        if (StringUtils.isEmpty(userForm.getId())) {
                messages.add(ActionMessages.GLOBAL_MESSAGE,
                    new ActionMessage("user.added", userForm.getUsername()));
                session.setAttribute(Globals.MESSAGE_KEY, messages);
                sendNewUserEmail(request, userForm);
                return mapping.findForward("addUser");
            } else {
                messages.add(ActionMessages.GLOBAL_MESSAGE,
                    new ActionMessage("user.updated.byAdmin",
                        userForm.getUsername()));
                saveMessages(request, messages);
                return mapping.findForward("edit");
            }
        }
    }
    public ActionForward search(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'search' method");
        }
        UserForm userForm = (UserForm) form;
                UserManager mgr = (UserManager) getBean("userManager");
        List users = mgr.getUsers(convert(userForm));
        request.setAttribute(Constants.USER_LIST, users);
        return mapping.findForward("list");
    }
    
    
    private void setupRoles(User user, HttpServletRequest request) {
        List roles = new ArrayList();
        if (user.getRoles() != null) {
            for (Iterator it = user.getRoles().iterator(); it.hasNext();) {
                UserRole role = (UserRole) it.next();
                                roles.add(new LabelValueBean(role.getRoleName(),
                          role.getRoleName()));
            }
        }
        request.setAttribute(Constants.USER_ROLES, roles);   
    }
    
    private void sendNewUserEmail(HttpServletRequest request, UserForm userForm)
    throws Exception {
        MessageResources resources = getResources(request);
                if (log.isDebugEnabled()) {
            log.debug("Sending user '" + userForm.getUsername()
                    + "' an account information e-mail");
        }
    
        User user = getUser(request.getSession());
        String fullName = user.getFirstName() + " " + user.getLastName();
        StringBuffer msg = new StringBuffer();
        msg.append(resources.getMessage("newuser.email.message", fullName));
        msg.append("\n\n" + resources.getMessage("userFormEx.username"));
        msg.append(": " + userForm.getUsername() + "\n");
        msg.append(resources.getMessage("userFormEx.password") + ": ");
        msg.append(userForm.getPassword());
        msg.append("\n\nLogin at: " + RequestUtils.serverURL(request) +
                       request.getContextPath());
    
        String subject = resources.getMessage("signup.email.subject");
    
        try {
                        MailUtil.sendTextMessage(Constants.DEFAULT_FROM,
                                     user.getEmail(), null,
                                     subject, msg.toString());
        } catch (MessagingException me) {
            log.warn("Failed to send Account Information e-mail");
        }   
    }
}