package com.k_int.ciim.ui.resources;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
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.MissingResourceException;
import com.k_int.ciim.ui.exceptions.NotAuthorisedException;
import com.k_int.ciim.ui.exceptions.ResourceDeletionException;
import com.k_int.ciim.ui.json.SchemaSectionJSON;
import com.k_int.ciim.ui.kernel.SchemaSectionQueryCore;
import com.k_int.ciim.ui.kernel.SchemaSectionTransactionCore;
import com.k_int.ciim.ui.kernel.SchemaTransactionCore;
import com.k_int.ciim.ui.ref.RoleDefinitionEnum;
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/schemas/{schema_id}/sections/{id}")
public class SchemaSectionResource extends AbstractResource
{
	private SchemaSectionJSON resource = null;
	
	@XmlTransient
	private SchemaSectionQueryCore ssqc = null;
	@XmlTransient
	private SchemaTransactionCore stc = null;
	@XmlTransient
	private SchemaSectionTransactionCore sstc = null;
	
	/* App Context setters */
	public void setSchemaSectionQueryCore(SchemaSectionQueryCore ssqc) 				{	this.ssqc = ssqc;	}
	public void setSchemaTransactionCore(SchemaTransactionCore stc) 				{	this.stc = stc;		}
	public void setSchemaSectionTransactionCore(SchemaSectionTransactionCore sstc) 	{	this.sstc = sstc;	}
	
	public SchemaSectionResource(){;}
	
	@GET
	@Produces({MediaType.TEXT_HTML,MediaType.APPLICATION_XHTML_XML})
	public Viewable getHtml(@PathParam("id") Long id) 
	{
		resource = new SchemaSectionJSON(ssqc.get(id));
		
		return new Viewable("index",this);
	}
	
	@GET
	@Produces("application/json")
	public SchemaSectionJSON getJson(@PathParam("id") Long id) 
	{		
		return new SchemaSectionJSON(ssqc.get(id));
	}
	
	@POST
	@Produces({MediaType.TEXT_PLAIN})
	public String actions(	@PathParam("schema_id") Long schema_id,
							@PathParam("id") Long id,
							@QueryParam("action") String action,
							@QueryParam("position") Integer position)
	{
		String retval = null;
		
		if(action.equalsIgnoreCase("delete"))
		{
			retval = this.delete(schema_id, id);
		}
		else if(action.equalsIgnoreCase("move"))
		{
			retval = this.move(schema_id, id, position);
		}
		
		return retval;
	}
	
	@POST
	@Consumes("application/x-www-form-urlencoded")
	@Produces({MediaType.TEXT_PLAIN})
	public String actions(	@PathParam("schema_id") Long schema_id,
							@PathParam("id") Long id,
							@QueryParam("action") String action,
							@QueryParam("position") Integer position,
							MultivaluedMap<String, String> form_params)
	{				
		String retval = null;
		
		if(action.equalsIgnoreCase("delete"))
		{
			retval = this.delete(schema_id, id);
		}
		else if(action.equalsIgnoreCase("update"))
		{
			retval = this.update(id, form_params);
		}
		else if(action.equalsIgnoreCase("move"))
		{
			retval = this.move(schema_id, id, position);
		}
		
		return retval;
	}
	
	private String move(Long schema_id, Long id, Integer position)
	{				
		String retval = "Failed to move section";
		
		if(this.meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			try
			{
				if(stc.moveSection(schema_id, id, position))
				{
					retval = "Successfully moved section";
				}
			}
			catch(MissingResourceException mre)
			{
				throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(mre.getMessage()).type("text/plain").build());
			}
		}
		else
		{
			throw new NotAuthorisedException();
		}  
		
		return retval;
	}
	
	private String update(Long id, MultivaluedMap<String, String> form_params)
	{				
		String retval = "Failed to update section";
		
		if(this.meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			//if null we have no validation errors
			if(validate(form_params) == null)
			{
				try
				{
					if(sstc.update(id, form_params))
					{
						retval = "Successfully updated section";
					}
				}
				catch(MissingResourceException mre)
				{
					throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(mre.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;
	}
	
	@DELETE
	@Produces({MediaType.TEXT_PLAIN})
	public String delete(	@PathParam("schema_id") Long schema_id,
							@PathParam("id") Long id)
	{
		String retval = "Failed to delete Schema Section.";
		
		if(this.meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			try
			{
				if(stc.removeSection(schema_id, id))
				{
					retval = "Schema Section successfully deleted.";		
				}
			}
			catch(MissingResourceException mre)//couldn't find schema section
			{
				throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(mre.getMessage()).type("text/plain").build());
			}
			catch(ResourceDeletionException rde)
			{
				throw new WebApplicationException(Response.status(Status.CONFLICT).entity(rde.getMessage()).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("name") == null || form_params.getFirst("name").trim().length() == 0)
		{
			return "name is required.";
		}
		
		return retval;
	}

	public SchemaSectionJSON getResource() 
	{
		return resource;
	}

	public void setResource(SchemaSectionJSON resource) 
	{
		this.resource = resource;
	}
}
