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

import java.io.IOException;

import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.apache.log4j.Logger;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import cz.muni.fi.lasaris.sbms.data.api.request.GroupedSnapshotRequest;
import cz.muni.fi.lasaris.sbms.data.api.request.SnapshotRequest;
import cz.muni.fi.lasaris.sbms.data.api.response.AggregationResponse;
import cz.muni.fi.lasaris.sbms.data.api.response.GroupedSnapshotResponse;
import cz.muni.fi.lasaris.sbms.data.api.response.SnapshotResponse;
import cz.muni.fi.lasaris.sbms.data.entities.Address;
import cz.muni.fi.lasaris.sbms.data.entities.values.RawValue;
import cz.muni.fi.lasaris.sbms.data.logic.ProviderManager;
import cz.muni.fi.lasaris.sbms.data.logic.DataCollector;
import cz.muni.fi.lasaris.sbms.data.util.Aggregator;



@Path("datapoints")
@PermitAll
public class DataPointsEndpoint {
	final static Logger logger = Logger.getLogger(DataPointsEndpoint.class);
	
	private DataCollector dc = new DataCollector(); 
	
	@RolesAllowed({"user","admin"})
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public SnapshotResponse getDataPoints(
			@QueryParam("json") String json,
			@QueryParam("cache") String cache
			) {
		
		ObjectMapper m = new ObjectMapper();
		m.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		try {
			logger.debug("Processing request...");
			logger.debug(json);
			SnapshotRequest readSpecs = m.readValue(json, SnapshotRequest.class);
			logger.debug(readSpecs);
			SnapshotResponse result = dc.getDataPointValues(readSpecs, allowCache(cache));
			logger.debug(result);
			return result;
		} catch (IOException e) {
			return SnapshotResponse.getErrorResponse("Unable to parse query:" + e);
		}
		
		
	}
	
	
	@RolesAllowed({"user","admin"})
	@GET
	@Path("/aggregated")
	@Produces(MediaType.APPLICATION_JSON)
	public AggregationResponse getAggregatedDataPoints(
			@QueryParam("json") String json,
			@QueryParam("aggregation") String agg,
			@QueryParam("cache") String cache
			) {
		ObjectMapper m = new ObjectMapper();
		try {
			logger.debug("Processing request...");
			logger.debug(json);
			SnapshotRequest readSpecs = m.readValue(json, SnapshotRequest.class);
			logger.debug(readSpecs);
			return dc.getDataPointsAggregation(readSpecs, Aggregator.getAggregation(agg), allowCache(cache));
		} catch (IOException e) {
			return AggregationResponse.getErrorResponse("Unable to parse query:" + e);
		}
	}


	@RolesAllowed({"user","admin"})
	@GET
	@Path("/grouped")
	@Produces(MediaType.APPLICATION_JSON)
	public GroupedSnapshotResponse getGroupedDataPoints(
			@QueryParam("json") String json,
			@QueryParam("cache") String cache
			) {
		ObjectMapper m = new ObjectMapper();
		try {
			logger.debug("Processing request...");
			logger.debug(json);
			GroupedSnapshotRequest readSpecs = m.readValue(json,GroupedSnapshotRequest.class);
			logger.debug(readSpecs);
			return dc.getDataPointGroupedValues(readSpecs, allowCache(cache));
		} catch (IOException e) {
			return GroupedSnapshotResponse.getErrorResponse("Unable to parse query:" + e);
		}
	}
	
	@RolesAllowed({"user","admin"})
	@GET
	@Path("/group-aggregated")
	@Produces(MediaType.APPLICATION_JSON)
	public AggregationResponse getGroupedAggregatedDataPoints(
			@QueryParam("json") String json,
			@QueryParam("aggregation") String agg,
			@QueryParam("cache") String cache
			) {
		ObjectMapper m = new ObjectMapper();
		try {
			logger.debug("Processing request...");
			logger.debug(json);
			GroupedSnapshotRequest readSpecs = m.readValue(json, GroupedSnapshotRequest.class);
			logger.debug(readSpecs);
			AggregationResponse result =  dc.getDataPointGroupAggregations(readSpecs, Aggregator.getAggregation(agg), allowCache(cache));
			logger.debug(result);
			return result;
		} catch (IOException e) {
			return AggregationResponse.getErrorResponse("Unable to parse query:" + e);
		}
	}
	
	@RolesAllowed({"user","admin"})
	@GET
	@Path("/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public SnapshotResponse getDataPoint(
			@PathParam("id") String idP, 
			@QueryParam("cache") String cache) {
		Address a = new Address(idP);
		RawValue v = ProviderManager.getDataPointsProvider(a.getProtocol()).getDataPointValue(a, allowCache(cache));
		return new SnapshotResponse(a, v);
	}
	
	private boolean allowCache(String cache) {
		return cache == null || cache.toLowerCase().equals("true") || cache.toLowerCase().equals("cache");  
	}
}
