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.PathParam;
import javax.ws.rs.Produces;
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.data.hdo.SchemaElementHDO;
import com.k_int.ciim.ui.exceptions.MissingResourceException;
import com.k_int.ciim.ui.exceptions.NotAuthorisedException;
import com.k_int.ciim.ui.exceptions.ResourceCreationException;
import com.k_int.ciim.ui.json.SchemaElementJSON;
import com.k_int.ciim.ui.kernel.SchemaElementQueryCore;
import com.k_int.ciim.ui.kernel.SchemaSectionTransactionCore;
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/{section_id}/elements")
public class SchemaElementResources extends AbstractResource 
{
	@XmlTransient
	private SchemaElementQueryCore seqc = null;
	@XmlTransient
	private SchemaSectionTransactionCore sstc = null;
	
	/* App Context setters */
	public void setSchemaElementQueryCore(SchemaElementQueryCore seqc) {	this.seqc = seqc;	}
	public void setSchemaSectionTransactionCore(SchemaSectionTransactionCore sstc) {	this.sstc = sstc;	}
	
	public SchemaElementResources(){;}
	
	@GET
	@Produces({MediaType.TEXT_HTML,MediaType.APPLICATION_XHTML_XML})
	public Viewable getHtml() 
	{
		return new Viewable("index",this);
	}
	
	@GET
	@Produces("application/json")
	public List<SchemaElementJSON> getJson(@PathParam("section_id") Long section_id) 
	{		
		return this.convertToJSON(seqc.getAll(section_id));
	}
	
	
	@POST 
	@Consumes("application/x-www-form-urlencoded")
	@Produces("application/json")
	public SchemaElementJSON create(@PathParam("schema_id") Long schema_id,
									@PathParam("section_id") Long section_id,
						 			MultivaluedMap<String, String> form_params)
	{
		SchemaElementJSON retval = null;
		
		//user must be an editor to create a new property
		if(this.meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			//if null we have no validation errors
			if(validate(form_params) == null)
			{
				try
				{
					//...so create schema section and add to schema
					SchemaElementHDO hdo = sstc.addElement(schema_id, section_id, form_params);
										
					//should we check if hdo is null and throw web app exception here?....probably not necessary for now...
					retval = new SchemaElementJSON(hdo);
				}
				catch(MissingResourceException mre)//couldn't find owning section
				{
					throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(mre.getMessage()).type("text/plain").build());
				}
				catch(ResourceCreationException rce)//couldn't create schema element
				{
					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("property") == null || form_params.getFirst("property").trim().length() == 0)
		{
			return "property is required.";
		}
		else if(form_params.getFirst("property") != null && form_params.getFirst("property").equalsIgnoreCase("Please Select"))
		{
			return "property is required.";
		}
		else if(form_params.getFirst("upperBound") != null && form_params.getFirst("upperBound").trim().length() > 0 )
		{
			Integer upperBound = Integer.parseInt(form_params.getFirst("upperBound"));
			
			if(form_params.getFirst("property_type") != null && form_params.getFirst("property_type").equalsIgnoreCase("text") && upperBound.intValue() > 2000)
			{
				return "upperBound value must not exceed 2000.";
			}
		}
		
		return retval;
	}
	
	/*
	 * Converts a list of SchemaElementHDO objects to a list of SchemaElementJSON objects
	 */
	private List<SchemaElementJSON> convertToJSON(List<SchemaElementHDO> elements)
	{
		List<SchemaElementJSON> retval = new ArrayList<SchemaElementJSON>();
		
		if(elements != null && elements.size() > 0)
		{
			// Iterate through hdo's ...
			for(SchemaElementHDO hdo : elements)
			{
				// ...and convert them to JSON
				retval.add(new SchemaElementJSON(hdo));
			}
		}
		
		return retval;
	}
}
