package com.k_int.ciim.ui.resources;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.DefaultValue;
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.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.ContextLinkHDO;
import com.k_int.ciim.data.hdo.SchemaHDO;
import com.k_int.ciim.ref.DataStatusEnum;
import com.k_int.ciim.ui.exceptions.NotAuthorisedException;
import com.k_int.ciim.ui.exceptions.ResourceCreationException;
import com.k_int.ciim.ui.json.AbstractJSON;
import com.k_int.ciim.ui.json.ContextLinkJSON;
import com.k_int.ciim.ui.json.PaginatorJSON;
import com.k_int.ciim.ui.kernel.ContextLinkQueryCore;
import com.k_int.ciim.ui.kernel.ContextLinkTransactionCore;
import com.k_int.ciim.ui.kernel.SchemaQueryCore;
import com.k_int.ciim.ui.ref.PermissionTypeEnum;
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/context_links")
public class ContextLinkResources extends AbstractResource
{
	@XmlTransient
	private ContextLinkQueryCore clqc = null;
	@XmlTransient
	private ContextLinkTransactionCore cltc = null;
	@XmlTransient
	private SchemaQueryCore sqc = null;
		
	/* App Context setters */
	public void setContextLinkQueryCore(ContextLinkQueryCore clqc) {	this.clqc = clqc;	}
	public void setContextLinkTransactionCore(ContextLinkTransactionCore cltc) {	this.cltc = cltc;	}
	public void setSchemaQueryCore(SchemaQueryCore sqc) {	this.sqc = sqc;	}
	
	public ContextLinkResources(){;}
	
	@GET
	@Produces({MediaType.TEXT_HTML,MediaType.APPLICATION_XHTML_XML})
	public Viewable getHtml() 
	{
		return new Viewable("index",this);
	}
	
	@GET
	@Produces({MediaType.APPLICATION_JSON})
	public Response getJSON(@QueryParam("resource_identifier") String resource_identifier,
							@QueryParam("context_id") Long context_id,
							@QueryParam("paginated") Boolean paginated,
							@QueryParam("start") Integer start,
							@QueryParam("rows") Integer rows,
							@DefaultValue("false") @QueryParam("outline") Boolean outline)
	{
		Response retval = null;
		
		if(resource_identifier != null)
		{
			//get all that are NOT archived
			retval = Response.ok(convertToJSON(clqc.getAll(resource_identifier, DataStatusEnum.ARCHIVED), outline.booleanValue())).build();
		}
		else if(paginated)
		{
			PaginatorJSON json = new PaginatorJSON();
			
			json.setTotalRecords(clqc.getCount(context_id, DataStatusEnum.ARCHIVED));
			json.setStartIndex(start);
			json.setRecordsReturned(rows);
			json.setPageSize(rows);
			json.setRecords(convertToJSON(clqc.getSubsetViaPaging(context_id, DataStatusEnum.ARCHIVED, start, rows), outline.booleanValue()));

			retval = Response.ok(json).build();
		}
		else
		{
			//get all that are NOT archived
			retval = Response.ok(convertToJSON(clqc.getAll(context_id, DataStatusEnum.ARCHIVED), outline.booleanValue())).build();
		}
		
		return retval;
	}
		
	@POST 
	@Produces({MediaType.TEXT_PLAIN})
	public String create(	@QueryParam("context_id") Long context_id, 
							@QueryParam("parent_identifier") String parent_identifier, 
							@QueryParam("parent_group_identifier") String parent_group_identifier)
	{
		String retval = null;
		
		//user must be an editor to create a new context link
		if(this.meetsRoleRequirement(RoleDefinitionEnum.CONFIGURED.toString()) 
		&& this.hasPermissions(context_id, PermissionTypeEnum.ADD))
		{
			//if null we have no validation errors
			if(validate(context_id,parent_identifier) == null)
			{
				try
				{
					//...so create Context Link
					ContextLinkHDO hdo = cltc.create(context_id,parent_identifier, parent_group_identifier, request.getUserPrincipal().getName());
					
					//if not null then the new context link has been successfully created
					if(hdo != null)
					{
						retval = hdo.getId().toString();
					}
				}
				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(context_id,parent_identifier)).type("text/plain").build());
			}
		}
		else
		{
			throw new NotAuthorisedException();
		}
		
		return retval;
	}
	
	private String validate(Long context_id, 
							String parent_identifier)
	{
		String retval = null;
		
		if(context_id == null)
		{
			return "context id has not been provided.";
		}
		else if(parent_identifier == null || parent_identifier.trim().length() == 0)
		{
			return "resource identifier has not been provided.";
		}
		
		return retval;
	}
	
	/*
	 * Converts a list of SchemaHDO objects to a list of SchemaJSON objects
	 */
	private List<AbstractJSON> convertToJSON(List<ContextLinkHDO> context_links, boolean outline)
	{
		List<AbstractJSON> retval = new ArrayList<AbstractJSON>();
		
		if(context_links != null && context_links.size() > 0)
		{
			// Iterate through hdo's ...
			for(ContextLinkHDO hdo : context_links)
			{	
				SchemaHDO schema_hdo = null;
				
				if(outline == false)
				{
					schema_hdo = sqc.get(hdo.getContext().getId(), hdo.getSourceDataType());
					// ...and convert them to JSON
				}
				
				retval.add(new ContextLinkJSON(hdo, schema_hdo));
			}
		}
		
		return retval;
	}
}
