/*
 * This file is part of DebGen Biobank Software developed by ASTRID Research.
 * All rights reserved. Reproduction, modification, use or disclosure
 * to third parties without express authority is forbidden.
 *
 * Copyright ASTRID Research Inc., Hungary, 2009-2011.
 *
 * ASTRID Research
 * Headquaters: Csapo utca 42. Debrecen H-4029 HUNGARY
 * Phone: +36-52-533-173        Fax: +36-52-533-174
 * Web: http://www.astrid.hu    E-mail: info@astrid.hu
 *
 * Project name: DebGen Biobank Software project.
 * URLS:
 * Developers: Istvan Zoltan Nagy (istvan.nagy@astrid.hu)
 */
package hu.astrid.debgen.useradmin.servlet;

import elements.Functions;
import hu.astrid.debgen.authentication.domain.DebGenUser;
import hu.astrid.debgen.authentication.exception.AccessDeniedException;
import hu.astrid.debgen.authentication.exception.InvalidPasswordException;
import hu.astrid.debgen.exception.ServerSideException;
import hu.astrid.debgen.exception.ValidationFailedException;
import hu.astrid.debgen.server.requestprocessor.ActionParameter;
import hu.astrid.debgen.server.requestprocessor.RequestTokenizer;
import hu.astrid.debgen.server.requestprocessor.exception.FormFillException;
import hu.astrid.debgen.server.requestprocessor.facade.RequestProcessorFacade;
import hu.astrid.debgen.useradmin.facade.UserAdminFacade;
import org.apache.log4j.Logger;
import org.hibernate.exception.ConstraintViolationException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 *
 * @author inagy
 */
public class UserAdminServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    static Logger logger = Logger.getLogger(UserAdminServlet.class);

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        logger.debug("doPost() called.");
        ActionParameter actionParameter = ActionParameter.getActionParameter(request);
        logger.debug(actionParameter);
        logger.debug(RequestTokenizer.getRequestData(request));
        String action = actionParameter.getAction();
        try {
            DebGenUser user = RequestProcessorFacade.getDebGenUser(request);
            if (!user.isUserAdministrator()) {
                throw new AccessDeniedException();
            }
            if (action.equals("listusers")) {
                loadUsers(request, response);
            } else if (action.equals("createuser")) {
                createUser(request, response);
            } else if (action.equals("changeuserpassword")) {
                changePassword(request, response);
            } else if (action.equals("saveuserpassword")) {
                savePassword(request, response);
            } else if (action.equals("saveuser")) {
                saveUser(request, response);
            } else if (action.equals("showuser")) {
                showUser(request, response);
            } else if (action.equals("disableuser")) {
                disableUser(request, response);
            } else if (action.equals("enableuser")) {
                enableUser(request, response);
            } else if (action.equals("deleteuser")) {
                deleteUser(request, response);
            } else {
                request.setAttribute("answer", true);
                request.getRequestDispatcher("index.jsp").forward(request, response);
            }
        } catch (AccessDeniedException ex) {
            request.setAttribute("answer", true);
            request.setAttribute("globalexception", new ServerSideException("Nincs jogosultsága a kérés befejezéséhez."));  //i18
            request.getRequestDispatcher("index.jsp").forward(request, response);
        } catch (Exception ex) {
            request.setAttribute("answer", true);
            request.setAttribute("globalexception", new ServerSideException("A kért erőforrás nem található, vagy a hivatkozás hibás."));  //i18
            request.getRequestDispatcher("index.jsp").forward(request, response);
        }

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    private void changePassword(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("changePassword() called.");
        loadUserAndSetRequest(request, response);
//        try {
//            Long id = new Long(request.getParameter("user"));
//            DebGenUser user = new UserAdminFacade().loadUser(id);
//            request.setAttribute("usr", user);
//            request.setAttribute("answer", true);
//            request.getRequestDispatcher("index.jsp").forward(request, response);
//        } catch (Exception ex) {
//            logger.error(ex);
//            throw ex;
//        }
    }

    private void createUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("createUser() called.");
        try {
            Long id = new Long(request.getParameter("user"));
            DebGenUser user = new UserAdminFacade().loadUser(id);
            request.setAttribute("usr", user);
        } catch (Exception ex) {
            //IGNORED, parameters can be empty
            logger.debug("No user found with this id, setting up create mode...");
        }
        request.setAttribute("answer", true);
        request.getRequestDispatcher("index.jsp").forward(request, response);

    }

    public void savePassword(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("savePassword() called.");
        DebGenUser user = null;
        UserAdminFacade userAdminFacade = new UserAdminFacade();
        try {
            Long id = new Long(request.getParameter("user"));
            user = userAdminFacade.loadUser(id);
            request.setAttribute("usr", user);
        } catch (Exception ex) {
            //IGNORED, parameters can be empty
            logger.debug("New user found, no problem!");
        }

        String newPassword = Functions.encodeString(request.getParameter("newpassword"));
        String newPasswordRetry = Functions.encodeString(request.getParameter("newpasswordretry"));

        try {
            userAdminFacade.changePassword(user, newPassword, newPasswordRetry);
            response.sendRedirect("showuser.html?user=" + user.getId());
        } catch (FormFillException ex) {
            logger.error(ex);
            request.setAttribute("exception", new ServerSideException(ex));
            request.setAttribute("answer", true);
            request.getRequestDispatcher("index.jsp").forward(request, response);
            return;
        } catch (InvalidPasswordException ex) {
            logger.error(ex);
            request.setAttribute("exception", new ServerSideException(ex));
            request.setAttribute("answer", true);
            request.getRequestDispatcher("index.jsp").forward(request, response);
            return;
        } catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
    }

    private void disableUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("disableUser() called.");
        try {
            Long id = new Long(request.getParameter("user"));
            UserAdminFacade userAdminFacade = new UserAdminFacade();
            userAdminFacade.setActiveUser(id, false);
            response.sendRedirect("showuser.html?user=" + id);
        } catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
    }

    private void enableUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("enableUser() called.");
        try {
            Long id = new Long(request.getParameter("user"));
            UserAdminFacade userAdminFacade = new UserAdminFacade();
            userAdminFacade.setActiveUser(id, true);
            response.sendRedirect("showuser.html?user=" + id);
        } catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
    }

    private void deleteUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("deleteUser() called.");
        try {
            Long id = new Long(request.getParameter("user"));
            UserAdminFacade userAdminFacade = new UserAdminFacade();
            if (RequestProcessorFacade.getDebGenUser(request).getId().equals(id)) {
                response.sendRedirect("showuser.html?user=" + id);
            } else {
                userAdminFacade.deleteUser(id);
                response.sendRedirect("listusers.html");
            }
        } catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
    }

    private void loadUsers(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("loadUsers() called.");
        List<DebGenUser> users = null;
        try {
            users = new UserAdminFacade().listUsers("fullName");
            request.setAttribute("users", users);
            request.setAttribute("answer", true);
            request.getRequestDispatcher("index.jsp").forward(request, response);
        } catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
    }

    private void saveUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("saveUser() called.");
        request.setAttribute("answer", true);
        try {
            Long id = 0L;
            DebGenUser user = null;
            boolean newUser = false;
            UserAdminFacade userAdminFacade = new UserAdminFacade();
            try {
                id = new Long(request.getParameter("id"));
                user = userAdminFacade.loadUser(id);
            } catch (Exception ex) {
                //IGNORED, parameters can be empty
                logger.debug("User is empty, but it's allowed!");
            }
            String passwordIfNew = null;
            if (user == null) {
                newUser = true;
                user = new DebGenUser();
                //user.setCreationTime(new Date());
                user.setActiveUser(true);
                passwordIfNew = DebGenUser.generatePassword();
                user.setHashedPassword(Functions.hashMD5(passwordIfNew));
            }
            user.convert(request);
            request.setAttribute("usr", user);
            if (newUser) {
                user = userAdminFacade.registerUser(user, passwordIfNew);
            } else {
                user = userAdminFacade.modifyUser(user);
            }
            response.sendRedirect("showuser.html?user=" + user.getId());
        } catch (ValidationFailedException ex) {
            logger.error(ex);
            request.setAttribute("exception", new ServerSideException(ex));
            request.getRequestDispatcher("index.jsp").forward(request, response);
        } catch (ConstraintViolationException ex) {
            logger.error(ex);
            request.setAttribute("exception", new ServerSideException((ex.getSQLException().getMessage().contains("@")) ? "Nem mentheti a felhasználót ezzel az e-mail címmel, mert a cím már foglalt. Kérem válasszon másikat." : "Nem mentheti a felhasználót ezzel a névvel, mert a név már foglalt. Kérem válasszon másikat."));  //i18
            request.getRequestDispatcher("index.jsp").forward(request, response);
        } catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
    }

    private void showUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("showUser() called.");
        loadUserAndSetRequest(request, response);
    }

    private void loadUserAndSetRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            Long id = new Long(request.getParameter("user"));
            DebGenUser user = new UserAdminFacade().loadUser(id);
            request.setAttribute("usr", user);
            request.setAttribute("answer", true);
            request.getRequestDispatcher("index.jsp").forward(request, response);
        } catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
    }
}
