package com.k_int.ciim.ui.resources;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import com.k_int.ciim.ui.exceptions.NotAuthorisedException;
import com.k_int.ciim.ui.exceptions.ResourceCreationException;
import com.k_int.ciim.ui.json.UserJSON;
import com.k_int.ciim.ui.kernel.IdentServiceQueryCore;
import com.k_int.ciim.ui.kernel.IdentServiceTransactionCore;
import com.k_int.ciim.ui.ref.RoleDefinitionEnum;
import com.k_int.svc.identity.datamodel.AuthenticationDetailsHDO;
import com.k_int.svc.identity.service.SystemUserDTO;
import com.sun.jersey.api.view.ImplicitProduces;
import com.sun.jersey.api.view.Viewable;

@XmlRootElement
@ImplicitProduces("text/html;qs=5") //for FireFox?
@XmlAccessorType(XmlAccessType.FIELD)
@Path("/resources/users")
public class UserResources extends AbstractResource
{
	@XmlTransient
	private IdentServiceQueryCore isqc = null;
	@XmlTransient
	private IdentServiceTransactionCore istc = null;

	/* App context setters */
	public void setIdentServiceQueryCore(IdentServiceQueryCore isqc){ this.isqc = isqc; }
	public void setIdentServiceTransactionCore(IdentServiceTransactionCore istc){ this.istc = istc; }
	  
	public UserResources(){;}
	
	@GET
	@Produces({MediaType.TEXT_HTML,MediaType.APPLICATION_XHTML_XML})
	public Viewable getHtml() 
	{
		if(meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			return new Viewable("index",this);
		}
		else
		{
			throw new NotAuthorisedException();
		}
	}
	
	@GET
	@Produces("application/json")
	public List<UserJSON> getJson() 
	{		
		if(meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			return this.convertToJSON(isqc.getUsers());
		}
		else
		{
			throw new NotAuthorisedException();
		}
	}
	
	@POST 
	@Consumes("application/x-www-form-urlencoded")
	@Produces({MediaType.TEXT_PLAIN})
	public String create(MultivaluedMap<String, String> form_params)
	{
		String retval = "Failed to create User.";
		
		//user must have the super role to create a new user
		if(this.meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			//if null we have no validation errors
			if(validate(form_params) == null)
			{
				try
				{
					//...so create user
					SystemUserDTO user_dto = istc.createUser(form_params);
					
					//if not null then the new user has been successfully created
					if(user_dto != null)
					{
						retval = "Successfully created user.";
					}
				}
				catch(ResourceCreationException rce)
				{
					throw new WebApplicationException(Response.status(Status.CONFLICT).entity(rce.getMessage()).type("text/plain").build());
				}
			}
			else
			{
				//return validation error message
				throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(validate(form_params)).type("text/plain").build());
			}
		}
		else
		{
			throw new NotAuthorisedException();
		}
		
		return retval;
	}
	
	private String validate(MultivaluedMap<String, String> form_params)
	{
		String retval = null;
		
		if(form_params.getFirst("username") == null || form_params.getFirst("username").trim().length() == 0)
		{
			retval = "Username is required.";
		}
		else if(form_params.getFirst("password") == null || form_params.getFirst("password").trim().length() == 0)
		{
			retval = "Password is required.";
		}
		else if(form_params.getFirst("password_confirm") == null || form_params.getFirst("password_confirm").trim().length() == 0)
		{
			retval = "Confirm Password is required.";
		}
		else if(form_params.getFirst("password").equals(form_params.getFirst("password_confirm")) == false)
		{
			retval = "Passwords entered must match.";
		}
				
		return retval;
	}
	
	@POST
	@Produces({MediaType.TEXT_PLAIN})
	public boolean hasPermission(	@QueryParam("principle") String user_principle, 
									@QueryParam("context") String context_id, 
									@QueryParam("context_link") String context_link_id, 
									@QueryParam("permission_type") String permission_type)
	{
		return isqc.hasPermission(user_principle, context_id, context_link_id, permission_type);
	}
	
	/*
	 * Converts a list of AuthenticationDetailsHDO objects to a list of UserJSON objects
	 */
	private List<UserJSON> convertToJSON(List<AuthenticationDetailsHDO> users)
	{
		List<UserJSON> retval = new ArrayList<UserJSON>();
		
		if(users != null && users.size() > 0)
		{
			// Iterate through hdo's ...
			for(AuthenticationDetailsHDO hdo : users)
			{
				// ...and convert them to JSON
				retval.add(new UserJSON(hdo, null));
			}
		}
		
		return retval;
	}
	
}
