package de.thomasjacob.improve.presentation.user;

import de.thomasjacob.improve.logic.DaoLocator;
import de.thomasjacob.improve.logic.project.Project;
import de.thomasjacob.improve.logic.project.ProjectDao;
import de.thomasjacob.improve.logic.user.Digester;
import de.thomasjacob.improve.logic.user.Role;
import de.thomasjacob.improve.logic.user.User;
import de.thomasjacob.improve.logic.user.UserDao;
import de.thomasjacob.improve.presentation.ImproveAction;
import de.thomasjacob.improve.presentation.login.LoginManager;
import de.thomasjacob.webcore.TechnicalException;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

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;


public class UserRHAction extends ImproveAction
{
	protected ActionForward executeChecked(ActionMapping mapping, ActionForm form, HttpServletRequest request,
		HttpServletResponse response) throws TechnicalException
	{
		HttpSession session = request.getSession();

		if (!LoginManager.getInstance(session).isLoggedIn())
		{
			return mapping.findForward("login");
		}

		User loggedInUser = LoginManager.getInstance(session).getUser();

		UserForm userForm = (UserForm) form;
		int userId = userForm.getUserId().equals("") ? 0 : Integer.parseInt(userForm.getUserId());

		boolean mayEditAccount = loggedInUser.isAdministrator() || loggedInUser.getId() == userId
			&& !loggedInUser.isGuest();
		if (!mayEditAccount)
		{
			getActionErrors(request).add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("LoginRHAction.priviledges"));
			return mapping.findForward("login");
		}

		if (request.getParameter("Save") != null)
		{
			return performSave(request, mapping, userForm, loggedInUser);
		}
		else if (request.getParameter("Add") != null)
		{
			return performAdd(request, mapping, userForm, loggedInUser);
		}
		else if (request.getParameter("Remove") != null)
		{
			return performRemove(request, mapping, userForm, loggedInUser);
		}
		else
		{
			return mapping.findForward("success");
		}
	}

	private ActionForward performSave(HttpServletRequest request, ActionMapping mapping, UserForm userForm, User loggedInUser) throws TechnicalException
	{
		if (!validateAndAddErrors(userForm, request, mapping).isEmpty())
		{
			return mapping.findForward("success");
		}

		UserDao userDao = DaoLocator.getInstance().getUserDao();

		int userId = userForm.getUserId().equals("") ? 0 : Integer.parseInt(userForm.getUserId());
		boolean nameExists = userDao.isUserNameExisting(userForm.getName(), userId);
		if (nameExists)
		{
			getActionErrors(request).add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("UserRHAction.nameExists"));
			return mapping.findForward("success");
		}

		if (loggedInUser.isAdministrator() && loggedInUser.getId() == userId
			&& (!Boolean.parseBoolean(userForm.getEnabled()) || !Boolean.parseBoolean(userForm.getAdministrator())))
		{
			getActionErrors(request)
				.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("UserRHAction.lockOutCancel"));
			return mapping.findForward("success");
		}

		if (Boolean.parseBoolean(userForm.getAdministrator()) && Boolean.parseBoolean(userForm.getGuest()))
		{
			getActionErrors(request)
				.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("UserRHAction.bothAdministratorAndGuest"));
			return mapping.findForward("success");
		}

		if (!userForm.getPassword1().equals(userForm.getPassword2()))
		{
			getActionErrors(request).add(ActionMessages.GLOBAL_MESSAGE,
				new ActionMessage("UserRHAction.noPasswordMatch"));
			return mapping.findForward("success");
		}

		if (userForm.getPassword1().equals("") && userForm.equals(""))
		{
			getActionErrors(request).add(ActionMessages.GLOBAL_MESSAGE,
				new ActionMessage("UserRHAction.fillOutPasswordFields"));
			return mapping.findForward("success");
		}

		User user;
		if (userId == 0)
		{
			user = new User();
		}
		else
		{
			user = userDao.getUserById(userId);
		}

		user.setName(userForm.getName());
		if (!userForm.getPassword1().equals(""))
		{
			user.setPassword(Digester.getInstance().hash(userForm.getPassword1()));
		}
		user.setEmail(userForm.getEmail());

		if (loggedInUser.isAdministrator())
		{
			user.setEnabled(Boolean.parseBoolean(userForm.getEnabled()));
			user.setAdministrator(Boolean.parseBoolean(userForm.getAdministrator()));
			user.setGuest(Boolean.parseBoolean(userForm.getGuest()));

			Set managerProjects = new HashSet(Arrays.asList(userForm.getManagerProjects()));
			Set developerProjects = new HashSet(Arrays.asList(userForm.getDeveloperProjects()));
			Set reporterProjects = new HashSet(Arrays.asList(userForm.getReporterProjects()));

			Iterator iterator = user.getRoles().values().iterator();
			while (iterator.hasNext())
			{
				Role role = (Role) iterator.next();
				String projectId = String.valueOf(role.getProject().getId());
				role.setManager(managerProjects.contains(projectId));
				role.setDeveloper(developerProjects.contains(projectId));
				role.setReporter(reporterProjects.contains(projectId));
			}
		}

		DaoLocator.getInstance().getUserDao().saveInTransaction(user);
		request.setAttribute("userId", new Integer(user.getId()));

		getActionMessages(request).add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("UserRHAction.saved"));
		return mapping.findForward("success");
	}

	private ActionForward performAdd(HttpServletRequest request, ActionMapping mapping, UserForm userForm, User loggedInUser) throws TechnicalException
	{
		int userId = Integer.parseInt(userForm.getUserId());
		UserDao userDao = DaoLocator.getInstance().getUserDao();
		User user = userDao.getUserById(userId);

		ProjectDao projectDao = DaoLocator.getInstance().getProjectDao();
		Project project = projectDao.getProjectById(Integer.parseInt(userForm.getNewProjectId()));

		if (user.getRole(project) == null)
		{
			Role role = new Role();
			role.setProject(project);
			role.setUser(user);
			role.setDeveloper(false);
			role.setManager(false);
			role.setReporter(false);
			user.getRoles().put(project, role);
		}

		DaoLocator.getInstance().getUserDao().saveInTransaction(user);
		request.setAttribute("userId", new Integer(user.getId()));

		getActionMessages(request).add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("UserRHAction.saved"));
		return mapping.findForward("success");
	}

	private ActionForward performRemove(HttpServletRequest request, ActionMapping mapping, UserForm userForm, User loggedInUser) throws TechnicalException
	{
		int userId = Integer.parseInt(request.getParameter("userId"));
		UserDao userDao = DaoLocator.getInstance().getUserDao();
		User user = userDao.getUserById(userId);

		int projectId = Integer.parseInt(request.getParameter("projectId"));
		ProjectDao projectDao = DaoLocator.getInstance().getProjectDao();
		Project project = projectDao.getProjectById(projectId);

		user.getRoles().remove(project);

		DaoLocator.getInstance().getUserDao().saveInTransaction(user);
		request.setAttribute("userId", new Integer(user.getId()));

		getActionMessages(request).add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("UserRHAction.saved"));
		return mapping.findForward("success");
	}
}
