package uk.ac.ebi.quickgo.rest.cache;

import com.google.common.base.Preconditions;
import java.time.Duration;
import java.time.LocalTime;
import java.util.function.Supplier;

/**
 * Holds algorithms to facilitate response caching.
 * <p>
 * Created by Tony on 04-Apr-17.
 */
public class CacheStrategy {

    /**
     * This algorithm models the following situation
     *
     * Time A - we are approaching the time of day when the data we use to populate requests is going to be
     * refreshed, therefore any subsequent requests to a RESTful service should have the following  header
     * <code>cache-control: max-age=0</code>
     * so User Agents, gateway caches don't cache this information (as it is likely to be out of data soon).
     *
     * Time B - we have high confidence data refresh will have taken place, and will not place until after Time A the
     * next day. Calculate the time left (in seconds) between a call to this method and Time A, and set the cache
     * control header so this data can be cached by UAs, or gateway caches for this period. The response HTTP header
     * will be the following
     * <code>cache-control: max-age=36000</code>
     * if there is exact ten hours left between a call to this method and Time A.
     *
     * See <a href="https://jakearchibald.com/2016/caching-best-practices/">Caching best practices & max-age
     * gotchas</a>,
     * <a href="https://www.mnot.net/cache_docs/">Caching Tutorial for Web Authors and Webmasters</a>,
     * <a href="https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers">Increasing Application Performance with HTTP Cache Headers | Heroku Dev Center</a>
     *
     * @param start The time of day after which a max-age time will be calculated, up until the end time, the next day
     * @param end The time of day after which the max-age will be reported as zero, so no more caching takes place
     * for all subsequent requests.
     * @return a String that holds the number of seconds left before the cut-of time after which requests will not be
     * cached.
     */
    public static Supplier<String> maxAgeTimeLeft(LocalTime start, LocalTime end) {

        Preconditions.checkArgument(start.isAfter(end));

        return () -> {
            long maxAge;
            final LocalTime now = LocalTime.now();
            if (now.isAfter(start)) {
                maxAge = Duration.between(now, LocalTime.MAX).getSeconds() + Duration.between(LocalTime.MIN, end).getSeconds();
            } else {
                if (now.isBefore(end)) {
                    maxAge = Duration.between(now, end).getSeconds();
                } else {
                    maxAge = 0;
                }
            }
            assert maxAge >= 0;
            return Long.toString(maxAge);
        };
    }
}

@@ -2247,16 +2247,109 @@
 r(end));
+%0A        final long secondsFromStartOfDayTillEndTime = secondsFromStartOfDayTillEndTime(end);
 %0A%0A      
@@ -2508,109 +2508,72 @@
 e = 
-Duration.between(now, LocalTime.MAX).getSeconds() + Duration.between(LocalTime.MIN, end).getSeconds()
+secondsFromNowToEndOfDay(now) + secondsFromStartOfDayTillEndTime
 ;%0A  
@@ -2665,46 +2665,45 @@
 e = 
-Duration.between(now, end).getSeconds(
+secondsTodayFromNowToEndTime(now, end
 );%0A 
@@ -2880,11 +2880,445 @@
 %7D;%0A    %7D
+%0A%0A    private static long secondsTodayFromNowToEndTime(LocalTime now, LocalTime end) %7B%0A        return Duration.between(now, end).getSeconds();%0A    %7D%0A%0A    private static long secondsFromStartOfDayTillEndTime(LocalTime end) %7B%0A        return Duration.between(LocalTime.MIN, end).getSeconds();%0A    %7D%0A%0A    private static long secondsFromNowToEndOfDay(LocalTime now) %7B%0A        return Duration.between(now, LocalTime.MAX).getSeconds();%0A    %7D
 %0A%7D%0A

Make the code more self documenting with same statements refactored to methods.