package com.tandogan.geostuff.opencagedata;

import com.tandogan.geostuff.opencagedata.entity.GeocodeResponse;
import com.tandogan.geostuff.opencagedata.entity.OpencageRate;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;

@Repository
public class GeocodeRepositoryImpl implements GeocodeRepository
{
    private final static Logger LOGGER = LoggerFactory.getLogger(GeocodeRepositoryImpl.class);

    private static final String API_KEY = "key";

    private static final String QUERY = "q";

    @Value("${API_KEY}")
    private String apiKey;

    @Value("${URL_BASE}")
    private String urlBase;

    private RestOperations template;

    private static final OpencageRate rate = new OpencageRate();

    private static final DateTime reset = new DateTime().withMillis(0);

    public GeocodeRepositoryImpl()
    {
        this.template = new RestTemplate();
    }

    public GeocodeRepositoryImpl(RestOperations template)
    {
        this.template = template;
    }

    public String getApiKey()
    {
        return apiKey;
    }

    public void setApiKey(String apiKey)
    {
        this.apiKey = apiKey;
    }

    public String getUrlBase()
    {
        return urlBase;
    }

    public void setUrlBase(String urlBase)
    {
        this.urlBase = urlBase;
    }

    public RestOperations getTemplate()
    {
        return template;
    }

    public void setTemplate(RestOperations template)
    {
        this.template = template;
    }

    public int getLimit()
    {
        return rate.getLimit();
    }

    public int getRemaining()
    {
        return rate.getRemaining();
    }

    public DateTime getReset()
    {
        return reset;
    }

    public GeocodeResponse query(String query)
    {
        URI serviceUrl = UriComponentsBuilder.fromUriString(getUrlBase())
                .queryParam(API_KEY, apiKey)
                .queryParam(QUERY, query)
                .build()
                .toUri();

        LOGGER.debug("REST template is {}", template);

        LOGGER.debug("geocoding query: {}", serviceUrl.toString());

        GeocodeResponse result = template.getForObject(serviceUrl, GeocodeResponse.class);

        if (result != null)
        {
            if (result.getRate() != null)
            {
                rate.setLimit(result.getRate().getLimit());
                rate.setRemaining(result.getRate().getRemaining());
                rate.setReset(result.getRate().getReset());

                reset.withMillis((long) (result.getRate().getReset()) * 1000L);
            }
        }

        LOGGER.debug("  {} of {} queries remaining", rate.getRemaining(), rate.getLimit());
        LOGGER.debug("  limit will be reset at {}, now it is {}", reset, DateTime.now());

        return result;
    }

    public GeocodeResponse reverse(double latitude, double longitude)
    {
        LOGGER.debug("reverse geocoding {}, {}", latitude, longitude);

        String query = "";

        query = query + latitude;

        query = query + "+";

        query = query + longitude;

        LOGGER.info("query is '{}'", query);

        return query(query);
    }
}

@@ -314,16 +314,108 @@
 .Value;%0A
+import org.springframework.http.HttpStatus;%0Aimport org.springframework.http.ResponseEntity;%0A
 import o
@@ -643,16 +643,71 @@
 t.URI;%0A%0A
+import static org.springframework.http.HttpStatus.OK;%0A%0A
 @Reposit
@@ -2573,16 +2573,90 @@
 result =
+ new GeocodeResponse();%0A        ResponseEntity%3CGeocodeResponse%3E response =
  templat
@@ -2667,14 +2667,14 @@
 tFor
-Object
+Entity
 (ser
@@ -2726,31 +2726,302 @@
 (res
-ult != null)%0A        %7B%0A
+ponse != null)%0A        %7B%0A            switch (response.getStatusCode())%0A            %7B%0A                // TODO proper handling of quota excessions%0A                case OK:%0A                    result = response.getBody();%0A%0A                    if (result != null)%0A                    %7B%0A            
     
@@ -3062,34 +3062,53 @@
 ll)%0A            
-%7B%0A
+            %7B%0A       
                 
@@ -3099,32 +3099,37 @@
                 
+     
 rate.setLimit(re
@@ -3148,32 +3148,44 @@
 ().getLimit());%0A
+            
                 
@@ -3244,32 +3244,44 @@
                 
+            
 rate.setReset(re
@@ -3325,16 +3325,28 @@
         
+     
+       
 reset.wi
@@ -3413,17 +3413,146 @@
         
-%7D
+            %7D%0A                    %7D%0A                    break;%0A%0A                default:%0A                    break;%0A            %7D%0A
 %0A       

Prepare for HTTP header processing