package com.k_int.ciim.ui.resources;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
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 org.springframework.beans.factory.annotation.Value;

import com.k_int.ciim.data.hdo.PropertyHDO;
import com.k_int.ciim.ref.PropertyTypeEnum;
import com.k_int.ciim.ui.exceptions.NotAuthorisedException;
import com.k_int.ciim.ui.exceptions.ResourceCreationException;
import com.k_int.ciim.ui.json.PropertyJSON;
import com.k_int.ciim.ui.kernel.PropertyQueryCore;
import com.k_int.ciim.ui.kernel.PropertyTransactionCore;
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/properties")
public class PropertyResources extends AbstractResource
{
	@XmlTransient
	private PropertyQueryCore pqc = null;
	@XmlTransient
	private PropertyTransactionCore ptc = null;
	
	private PropertyTypeEnum[] property_types = PropertyTypeEnum.values();
	private String[] mapping_keys = null;
	
	@Value("${ui.mapping.keys}") 
	private String	raw_mapping_keys;
	
	/* App Context setters */
	public void setPropertyQueryCore(PropertyQueryCore pqc) {	this.pqc = pqc;	}
	public void setPropertyTransactionCore(PropertyTransactionCore ptc) {	this.ptc = ptc;	}
	
	public PropertyResources(){;}
	
	@PostConstruct
	public void init()
	{		
		mapping_keys = raw_mapping_keys.split(",", 0);	
	}
	
	@GET
	@Produces({MediaType.TEXT_HTML,MediaType.APPLICATION_XHTML_XML})
	public Viewable getHtml() 
	{
		return new Viewable("index",this);
	}
	
	@GET
	@Produces("application/json")
	public List<PropertyJSON> getJson(	@QueryParam("property_type") String property_type,
										@QueryParam("schema_id") Long schema_id) 
	{	
		PropertyTypeEnum type = null;
		
		if(property_type != null && property_type.trim().length() > 0)
		{
			if(property_type.equalsIgnoreCase("Please Select"))
			{
				//return empty list
				return this.convertToJSON(null);
			}
				
			type = PropertyTypeEnum.valueOf(property_type.toUpperCase());
		}
		
		return this.convertToJSON(pqc.getAll(type, schema_id));
	}
	
	@POST
	@Consumes("application/x-www-form-urlencoded")
	@Produces({MediaType.TEXT_PLAIN})
	public String create(MultivaluedMap<String, String> form_params)
	{
		String retval = "Failed to create property";
		
		//user must be an editor to create a new property
		if(this.meetsRoleRequirement(RoleDefinitionEnum.SUPER.toString()))
		{
			//if null then no validation errors...
			if(validate(form_params) == null)
			{
				try
				{
					//...so create property
					PropertyHDO hdo = ptc.create(form_params);
					
					//if not null then the new property has been successfully created
					if(hdo != null)
					{
						retval = "Successfully created property " + hdo.getName() + ".";
					}
				}
				catch(ResourceCreationException rce)
				{
					throw new WebApplicationException(Response.status(Status.CONFLICT).entity(rce.getMessage()).type("text/plain").build());
				}
			}
			else
			{
				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("name") == null || form_params.getFirst("name").trim().length() == 0)
		{
			return "name is required.";
		}
		else if(form_params.getFirst("property_type") == null || form_params.getFirst("property_type").trim().length() == 0)
		{
			return "type is required.";
		}
		else if((form_params.getFirst("property_type").equalsIgnoreCase("media") == false) && (form_params.getFirst("mapping_key") == null || form_params.getFirst("mapping_key").trim().length() == 0))
		{
			return "mapping key is required.";
		}
		
		return retval;
	}
	
	/*
	 * Converts a list of PropertyHDO objects to a list of PropertyJSON objects
	 */
	private List<PropertyJSON> convertToJSON(List<PropertyHDO> properties)
	{
		List<PropertyJSON> retval = new ArrayList<PropertyJSON>();
		
		if(properties != null && properties.size() > 0)
		{
			// Iterate through hdo's ...
			for(PropertyHDO hdo : properties)
			{
				// ...and convert them to JSON
				retval.add(new PropertyJSON(hdo));
			}
		}
		
		return retval;
	}
	
	public PropertyTypeEnum[] getPropertyTypes() 
	{
		return property_types;
	}
	public String[] getMappingKeys() {
		return mapping_keys;
	}
	public void setMappingKeys(String[] mappingKeys) {
		mapping_keys = mappingKeys;
	}
}
