package cz.muni.fi.lasaris.sbms.api;

import java.net.URI;

import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
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.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import cz.muni.fi.lasaris.sbms.api.entities.Address;
import cz.muni.fi.lasaris.sbms.api.entities.Influence;
import cz.muni.fi.lasaris.sbms.api.entities.ObservedProperty;
import cz.muni.fi.lasaris.sbms.api.entities.Scope;
import cz.muni.fi.lasaris.sbms.api.request.AddressRequest;
import cz.muni.fi.lasaris.sbms.api.request.Insert;
import cz.muni.fi.lasaris.sbms.api.response.AddressResponse;
import cz.muni.fi.lasaris.sbms.api.response.GroupedResponse;
import cz.muni.fi.lasaris.sbms.api.response.InfluenceResponse;
import cz.muni.fi.lasaris.sbms.model.Fields;
import cz.muni.fi.lasaris.sbms.model.ModelUpdater;
import cz.muni.fi.lasaris.sbms.model.QueryParser;

@Path("influence")
@PermitAll
public class InfluencesEndpoint {
	final static Logger logger = Logger.getLogger(InfluencesEndpoint.class);
	
	@GET
	@Path("/influencing")
	@Produces(MediaType.APPLICATION_JSON)
	public AddressResponse getInfluencing(
		@QueryParam("influenced.scope.bimId") String scopeBimIdP,
		@QueryParam("influenced.property.domain") String propDomP,
		@QueryParam("influenced.property.quality") String propQualityP//,
		//@QueryParam("grouping") String groupingP,
		//@QueryParam("fields") String fieldsP
		) {
		
		if(scopeBimIdP == null && propDomP == null && propQualityP == null) {
			return AddressResponse.getErrorResponse("Parameters must be set");
		}
		
		if(!(propDomP == null && propQualityP == null) 
				&& (propDomP == null || propQualityP == null)) {
			return AddressResponse.getErrorResponse("Both parameters (domain, quality) must be set");
		}
		
		if(propDomP != null && scopeBimIdP == null) {
			return AddressResponse.getErrorResponse("Scope must be set when property is set");
		}
		
		AddressRequest r = new AddressRequest();
	
		Address a = new Address();
		r.setAddress(a);
		
		Influence i = new Influence();
		if(StringUtils.isNotBlank(scopeBimIdP)) {
			i.setScope(new Scope());
			i.getScope().setBimId(scopeBimIdP);
		}
		if(StringUtils.isNotBlank(propDomP)) {
			i.setProperty(new ObservedProperty());
			i.getProperty().setDomain(propDomP);
		}
		if(StringUtils.isNotBlank(propQualityP)){
			if(i.getProperty() == null) {
				i.setProperty(new ObservedProperty());
			}
			i.getProperty().setQuality(propQualityP);
		}
		a.setInfluenced(i);
		//r.parseResponseFields(fieldsP);
		r.getResponseFields().addAll(Fields.INFLUENCE_FIELDS);
		//r.setGrouping(groupingP);
		return QueryParser.getInfluencingResponse(r);
	}
	
	@GET
	@Path("/influenced")
	@Produces(MediaType.APPLICATION_JSON)
	public InfluenceResponse getInfluenced(
			@QueryParam("bmsId") String bmsIdP) {
		
		if(StringUtils.isBlank(bmsIdP)) {
			GroupedResponse.getErrorResponse("bmsId must be set");
		}
		AddressRequest r = new AddressRequest(new Address(bmsIdP));
		r.getResponseFields().addAll(Fields.INFLUENCE_FIELDS);
		return QueryParser.getInfluencedResponse(r);
	}
	
	@Context
	private UriInfo uriInfo;
	
	@RolesAllowed("admin")
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	public Response InsertAddressInfo(Insert insert) {
		try {
			if(insert.getAddress() != null && ModelUpdater.insertAddress(insert)) {
				URI createdUri = new URI(uriInfo.getAbsolutePath().toString() + insert.getAddress().getResourceId());
				return Response.created(createdUri).build();
			} else {
				return Response.status(Response.Status.BAD_REQUEST).entity("Invalid JSON data - see server log").build();
			}
		} catch (Exception e) {
			logger.error(e);
			return Response.serverError().build();
		}
	}
	
}
