package foodtruck.server.resources;

import java.util.logging.Logger;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.common.base.Throwables;
import com.google.inject.Inject;

import org.codehaus.jettison.json.JSONException;
import org.joda.time.DateTime;

import foodtruck.monitoring.Counter;
import foodtruck.monitoring.DailyScheduleCounter;
import foodtruck.monitoring.HourlyScheduleCounter;
import foodtruck.schedule.ScheduleCacher;
import foodtruck.server.resources.json.DailyScheduleWriter;
import foodtruck.truckstops.FoodTruckStopService;
import foodtruck.util.Clock;

/**
 * @author aviolette
 * @since 1/27/13
 */
@Path("/daily_schedule") @Produces(MediaType.APPLICATION_JSON)
public class DailyScheduleResource {
  private static final Logger log = Logger.getLogger(DailyScheduleResource.class.getName());
  private final FoodTruckStopService truckService;
  private final Clock clock;
  private final AuthorizationChecker checker;
  private final ScheduleCacher scheduleCacher;
  private final DailyScheduleWriter dailyScheduleWriter;
  private final MemcacheService memcacheService;
  private final Counter dailyCounter;
  private final Counter hourlyCounter;

  @Inject
  public DailyScheduleResource(FoodTruckStopService foodTruckService, Clock clock, AuthorizationChecker checker,
      ScheduleCacher scheduleCacher, DailyScheduleWriter writer, MemcacheService memcacheService,
      @DailyScheduleCounter Counter counter, @HourlyScheduleCounter Counter hourlyCounter) {
    this.truckService = foodTruckService;
    this.clock = clock;
    this.checker = checker;
    this.scheduleCacher = scheduleCacher;
    this.dailyScheduleWriter = writer;
    this.memcacheService = memcacheService;
    this.dailyCounter = counter;
    this.hourlyCounter = hourlyCounter;
  }

  @GET @Produces("application/json")
  public String findForDay(@QueryParam("appKey") final String appKey, @QueryParam("from") final long from) {
    dailyCounter.increment(appKey);
    hourlyCounter.increment(appKey);
    checker.requireAppKeyWithCount(appKey, hourlyCounter.getCount(appKey), dailyCounter.getCount(appKey));
    if (from > 0) {
      try {
        return dailyScheduleWriter.asJSON(truckService.findStopsForDayAfter(new DateTime(from, clock.zone()))).toString();
      } catch (JSONException e) {
        throw Throwables.propagate(e);
      }
    }
    String payload = scheduleCacher.findSchedule();
    if (payload == null) {
      try {
        log.info("Pulled schedule from db");
        payload = dailyScheduleWriter.asJSON(truckService.findStopsForDay(clock.currentDay())).toString();
        scheduleCacher.saveSchedule(payload);
        return payload;
      } catch (JSONException e) {
        throw Throwables.propagate(e);
      }
    }
    log.info("Pulled schedule from cache");
    return payload;
  }
}

@@ -205,24 +205,67 @@
 MediaType;%0A%0A
+import com.google.api.client.util.Strings;%0A
 import com.g
@@ -306,24 +306,24 @@
 cheService;%0A
-
 import com.g
@@ -465,16 +465,95 @@
 ateTime;
+%0Aimport org.joda.time.LocalDate;%0Aimport org.joda.time.format.DateTimeFormatter;
 %0A%0Aimport
@@ -864,16 +864,57 @@
 l.Clock;
+%0Aimport foodtruck.util.DateOnlyFormatter;
 %0A%0A/**%0A *
@@ -1418,32 +1418,77 @@
 emcacheService;%0A
+  private final DateTimeFormatter formatter;%0A
   private final 
@@ -1859,16 +1859,70 @@
 yCounter
+,%0A      @DateOnlyFormatter DateTimeFormatter formatter
 ) %7B%0A    
@@ -2209,16 +2209,48 @@
 ounter;%0A
+    this.formatter = formatter;%0A
   %7D%0A%0A  @
@@ -2388,16 +2388,55 @@
 ong from
+,%0A      @QueryParam(%22for%22) String aDate
 ) %7B%0A    
@@ -2611,23 +2611,395 @@
 pKey));%0A
-
     if 
+(!Strings.isNullOrEmpty(aDate)) %7B%0A      LocalDate localDate = formatter.parseLocalDate(aDate);%0A      log.info(%22Pulled schedule for day: %22 + aDate);%0A      try %7B%0A        return dailyScheduleWriter.asJSON(truckService.findStopsForDay(formatter.parseLocalDate(aDate))).toString();%0A      %7D catch (JSONException e) %7B%0A        throw Throwables.propagate(e);%0A      %7D%0A    %7D else if 
 (from %3E 

Add ability to retrieve advance schedule