package com.mason.server.controller;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.google.appengine.api.datastore.KeyFactory;
import com.mason.server.dao.jdo.ProjectAccessDAO;
import com.mason.server.dao.jdo.UmlElementContainerDAO;
import com.mason.server.dao.jdo.UmlElementDAO;
import com.mason.server.dao.jdo.ProjectDAO;
import com.mason.server.dao.jdo.UmlModelDAO;
import com.mason.server.dao.jdo.UserDAO;
import com.mason.server.dao.jdo.ViewDAO;
import com.mason.server.exception.ResourceNotFoundException;
import com.mason.server.model.DbUser;
import com.mason.server.model.Project;
import com.mason.server.model.ProjectAccess;
import com.mason.server.model.UmlModel;

@Controller
public class MainController {

	private static UserDAO userDAO = new UserDAO();
	private static ProjectDAO projectDAO = new ProjectDAO();
	private static ProjectAccessDAO projectAccessDAO = new ProjectAccessDAO();
	private static UmlModelDAO umlModelDAO = new UmlModelDAO();
	private static ViewDAO viewDAO = new ViewDAO();
	private static UmlElementDAO elementDAO = new UmlElementDAO();
	private static UmlElementContainerDAO elementContainerDAO = new UmlElementContainerDAO();

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String index(ModelMap model, Principal principal) {
		return "welcome";
	}

	@RequestMapping(value = "/user", method = RequestMethod.GET)
	public String user(ModelMap model, Principal principal) {
		if (principal != null) {
			return "redirect:/" + principal.getName();
		}
		return "welcome";
	}

	@RequestMapping(value = "/welcome", method = RequestMethod.GET)
	public String welcome(ModelMap model, Principal principal) {
		return "welcome";
	}

	@RequestMapping(value = "/denied", method = RequestMethod.GET)
	public String denied(ModelMap model, Principal principal) {
		return "denied";
	}

	@RequestMapping(value = "/{usernameSlug}", method = RequestMethod.GET)
	public String getUser(@PathVariable String usernameSlug,
			HttpServletRequest request, ModelMap model) {
		DbUser user = getUserByUsername(usernameSlug);
		model.addAttribute("user", user);
		
		List<ProjectAccess> projectAccesses = projectAccessDAO.getAllByUserId(user.getId());
		
		List<Project> projects = new ArrayList<Project>();
		
		for (ProjectAccess pa : projectAccesses) {
			if (pa.getRole() != ProjectAccess.Role.NONE) {
				projects.add(projectDAO.get(pa.getProjectId()));
			}
		}
		model.addAttribute("projectList", projects);
		
		List<UmlModel> models = new ArrayList<UmlModel>();
		
		for (Project p : projects ) {
			models.addAll(umlModelDAO.getAllByProjectId(p.getId()));
		}

		
		model.addAttribute("umlModelList", models);
		
		Set<DbUser> owners = new HashSet<DbUser>();
		
		for (Project p : projects ) {
			owners.add(userDAO.get(p.getOwnerId()));
		}

		model.addAttribute("ownerList", owners);
		
		return "user/userOverview";
	}

	@RequestMapping(value = "/workspace/{slug}", method = RequestMethod.GET)
	public String getWorkspace(@PathVariable String slug, HttpServletRequest request, ModelMap model,
			Principal principal) {
		DbUser user = getUserByUsername(principal.getName());		
		model.addAttribute("user", user);

		UmlModel umlModel = umlModelDAO.get(KeyFactory.stringToKey(slug).getId());
		
		//check if got access
		ProjectAccess pa = projectAccessDAO.getAccessUserToProject(umlModel.getProjectId(), user.getId());
		
		if (pa == null || pa.getRole() == ProjectAccess.Role.NONE ) {
			return "redirect:/denied";
		}
		
		model.addAttribute("umlModel", umlModel);
		model.addAttribute("viewList", viewDAO.getAllByModelId(umlModel.getId()));
		model.addAttribute("elementList", elementDAO.getAllByModelId(umlModel.getId()));

		return "workspace/umlModelWorkspace";
	}

	@RequestMapping(value = "/{usernameSlug}/{projectSlug}", method = RequestMethod.GET)
	public String getProjectByUser(@PathVariable String usernameSlug,
			@PathVariable String projectSlug, ModelMap model) {
		DbUser user = getUserByUsername(usernameSlug);
		Project project = getProjectBySlug(projectSlug, user.getId());
		model.addAttribute("project", project);
		model.addAttribute("user", user);
		model.addAttribute("umlModelList",
				umlModelDAO.getAllByProjectId(project.getId()));
		return "project/projectOverview";
	}

	@RequestMapping(value = "/{usernameSlug}/{projectSlug}/access", method = RequestMethod.GET)
	public String getProjectAccessPage(@PathVariable String usernameSlug,
			@PathVariable String projectSlug, ModelMap model) {

		DbUser user = getUserByUsername(usernameSlug);
		Project project = getProjectBySlug(projectSlug, user.getId());
		
		List<ProjectAccess> accesses =  projectAccessDAO.getAllByProjectId(project.getId());
		
		List<DbUser> users = new ArrayList<DbUser>();
		
		for (ProjectAccess pa : accesses) {
			users.add(userDAO.get(pa.getUserId()));
		}

		model.addAttribute("project", project);
		model.addAttribute("projectAccessList", accesses);
		model.addAttribute("userList", users);
		model.addAttribute("accessRoles", ProjectAccess.getAccessRoles());
		model.addAttribute("users", userDAO.getAll());
		
		ProjectAccess pa = new ProjectAccess();
		pa.setProjectId(project.getId());
		
		model.addAttribute("projectAccess", pa);
		
		return "projectAccess/projectAccessOverview";
	}

	@RequestMapping(value = "/user/list", method = RequestMethod.GET)
	public String overview(Model model) {
		model.addAttribute("userList", userDAO.getAll());
		return "user/userList";
	}

	@RequestMapping(value = "/project/list", method = RequestMethod.GET)
	public String listProject(Model model) {
		model.addAttribute("projectList", projectDAO.getAll());
		return "project/projectList";
	}

	@RequestMapping(value = "/projectAccess/list", method = RequestMethod.GET)
	public String listProjectAccess(Model model) {
		model.addAttribute("projectAccessList", projectAccessDAO.getAll());
		return "projectAccess/projectAccessList";
	}

	@RequestMapping(value = "/model/list", method = RequestMethod.GET)
	public String listModel(Model model) {
		model.addAttribute("umlModelList", umlModelDAO.getAll());
		return "model/umlModelList";
	}

	@RequestMapping(value = "/view/list", method = RequestMethod.GET)
	public String listView(Model model) {
		model.addAttribute("viewList", viewDAO.getAll());
		return "view/viewList";
	}

	@RequestMapping(value = "/element/list", method = RequestMethod.GET)
	public String listElement(Model model) {
		model.addAttribute("elementList", elementDAO.getAll());
		return "element/elementList";
	}

	@RequestMapping(value = "/elementContainer/list", method = RequestMethod.GET)
	public String listElementContainer(Model model) {
		model.addAttribute("elementContainerList", elementContainerDAO.getAll());
		return "elementContainer/elementContainerList";
	}

	public static DbUser getUserByUsername(String username) {
		DbUser user = userDAO.getByUsername(username);
		if (user == null) {
			throw new ResourceNotFoundException("User: " + username);
		}

		return user;
	}

	public static Project getProjectBySlug(String projectSlug, long ownerId) {
		Project p = projectDAO.getBySlug(projectSlug, ownerId);

		if (p == null) {
			throw new ResourceNotFoundException("Project:" + projectSlug
					+ " OwnerId:" + ownerId);
		}

		return p;
	}

}
