package org.fluxtream.core.api;
import com.google.gson.Gson;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import com.wordnik.swagger.annotations.Authorization;
import org.fluxtream.core.Configuration;
import org.fluxtream.core.aspects.FlxLogger;
import org.fluxtream.core.auth.AuthHelper;
import org.fluxtream.core.domain.metadata.FoursquareVenue;
import org.fluxtream.core.domain.metadata.VisitedCity;
import org.fluxtream.core.mvc.models.VisitedCityModel;
import org.fluxtream.core.services.GuestService;
import org.fluxtream.core.services.MetadataService;
import org.fluxtream.core.utils.TimeUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
/**
* User: candide
* Date: 05/06/13
* Time: 12:07
*/
@Path("/v1/metadata")
@Api(value = "/metadata", description = "Location/Timezone query and disambiguation endpoints.",
authorizations = {@Authorization(value="oauth2")})
@Component("RESTMetadataController")
@Scope("request")
public class MetadataController {
FlxLogger logger = FlxLogger.getLogger(MetadataController.class);
@Autowired
MetadataService metadataService;
@Autowired
GuestService guestService;
@Autowired
Configuration env;
Gson gson = new Gson();
@POST
@Path(value="/mainCity/date/{date}")
@ApiOperation(value = "Set the main city for a given day using lat/lon coordinates.", response = String.class,
notes="(we figure out the actual city from the coordinates)",
authorizations = {@Authorization(value="oauth2")})
public Response setDayMainCity(@ApiParam(value="Latitude", required=true) @FormParam("latitude") float latitude,
@ApiParam(value="Longitude", required=true) @FormParam("longitude") float longitude,
@ApiParam(value="Date (YYYY-MM-DD)", required=true) @PathParam("date") String date) {
final long guestId = AuthHelper.getGuestId();
StringBuilder sb = new StringBuilder("module=API component=calendarController action=setDayMainCity")
.append(" guestId=").append(guestId);
logger.info(sb.toString());
metadataService.setDayMainCity(guestId, latitude, longitude, date);
return Response.ok("OK").build();
}
@DELETE
@Path(value="/mainCity/date/{date}")
@ApiOperation(value = "Remove cities that have been manually entered by the end-user.", response = String.class,
authorizations = {@Authorization(value="oauth2")})
public Response resetDayMainCity(@ApiParam(value="Date (YYYY-MM-DD)", required=true) @PathParam("date") String date) {
final long guestId = AuthHelper.getGuestId();
StringBuilder sb = new StringBuilder("module=API component=calendarController action=resetDayMainCity")
.append(" guestId=").append(guestId);
logger.info(sb.toString());
metadataService.resetDayMainCity(guestId, date);
return Response.ok("OK").build();
}
@POST
@Path(value="/mainCity/{visitedCityId}/date/{date}")
@ApiOperation(value = "Set a given city and associated timezone to be the reference for a given day.", response = String.class)
public Response setDayMainCity(@ApiParam(value="ID of the city (as in /metadata/cities)", required=true) @PathParam("visitedCityId") long visitedCityId,
@ApiParam(value="Date (YYYY-MM-DD)", required=true) @PathParam("date") String date) {
final long guestId = AuthHelper.getGuestId();
StringBuilder sb = new StringBuilder("module=API component=calendarController action=setDayMainCity")
.append(" guestId=").append(guestId);
logger.info(sb.toString());
metadataService.setDayMainCity(guestId, visitedCityId, date);
return Response.ok("OK").build();
}
@GET
@Path(value="/foursquare/venue/{venueId}")
@ApiOperation(value = "Retrieve the Foursquare info for a given venue ID (results are cached)", response = FoursquareVenue.class)
@Produces({ MediaType.APPLICATION_JSON } )
public Response getFoursquareVenue(@ApiParam(value="Foursquare venue ID", required=true) @PathParam("venueId") String venueId) {
// this doesn't seem to have any effect, i.e. the cache-control header is alwasy set to no-cache
// needs invistigating...
CacheControl cc = new CacheControl();
// cache for a month
cc.setNoCache(false);
cc.setMaxAge(86400*31);
final FoursquareVenue foursquareVenue = metadataService.getFoursquareVenue(venueId);
Response.ResponseBuilder builder = Response.ok(foursquareVenue);
builder.cacheControl(cc);
return builder.build();
}
@GET
@Path(value = "/checkIn/{ipAddress}")
@ApiOperation(value = "Use ip2location lookup to guess the user's location based on his IP address", response = String.class,
notes="The resulting location will interpreted as a place the user was at at that moment")
public Response checkIn(@ApiParam(value="The end-users terminal IP address", required=true) @PathParam("ipAddress") String ipAddress){
final long guestId = AuthHelper.getGuestId();
try {
guestService.checkIn(guestId, ipAddress);
return Response.ok("Guest successfully checked in").build();
}
catch (IOException e) {
return Response.serverError().entity("Unexpected error while checking in: " + e.getMessage()).build();
}
}
@GET
@Path(value = "/cities")
@ApiOperation(value = "The list of cities visited by the user during a given time interval", responseContainer = "Array",
response = VisitedCityModel.class)
@Produces({MediaType.APPLICATION_JSON})
public String getCitiesForRange(@ApiParam(value="Start of given time interval", required=true) @QueryParam("start") long start,
@ApiParam(value="End of given time interval", required=true) @QueryParam("end") long end){
TreeSet<String> dates = new TreeSet<String>();
DateTime startDate = new DateTime(start);
DateTime endDate = new DateTime(end);
while (startDate.isBefore(endDate)){
dates.add(TimeUtils.dateFormatter.print(startDate));
startDate = startDate.plusDays(1);
}
String finalDate = TimeUtils.dateFormatter.print(endDate);
if (!dates.contains(finalDate)) dates.add(finalDate);
List<VisitedCityModel> cities = new ArrayList<VisitedCityModel>();
for (VisitedCity city : metadataService.getConsensusCities(AuthHelper.getGuestId(), dates)){
cities.add(new VisitedCityModel(city,env));
}
return gson.toJson(cities);
}
}