// Path: aula21-iterator-vs-stream/src/main/java/weather/data/WeatherWebApi.java
// public class WeatherWebApi {
// 
//     private static final String WEATHER_TOKEN;
//     private static final String WEATHER_HOST = "http://api.worldweatheronline.com";
//     private static final String WEATHER_PAST = "/premium/v1/past-weather.ashx";
//     private static final String WEATHER_PAST_ARGS =
//             "?q=%s&date=%s&enddate=%s&tp=24&format=csv&key=%s";
//     private static final String WEATHER_SEARCH="/premium/v1/search.ashx?query=%s";
//     private static final String WEATHER_SEARCH_ARGS="&format=tab&key=%s";
// 
//     static {
//         try {
//             URL keyFile = ClassLoader.getSystemResource("worldweatheronline-app-key.txt");
//             if(keyFile == null) {
//                throw new IllegalStateException(
//                        "YOU MUST GOT a KEY in developer.worldweatheronline.com and place it in src/main/resources/worldweatheronline-app-key.txt");
//             } else {
//                 InputStream keyStream = keyFile.openStream();
//                 try (BufferedReader reader = new BufferedReader(new InputStreamReader(keyStream))) {
//                     WEATHER_TOKEN = reader.readLine();
//                 }
//             }
//         } catch (IOException e) {
//             throw new UncheckedIOException(e);
//         }
//     }
// 
//     private final IRequest req;
// 
//     public WeatherWebApi(IRequest req) {
//         this.req = req;
//     }
// 
//     /**
//      * E.g. http://api.worldweatheronline.com/free/v2/search.ashx?query=oporto&format=tab&key=*****
//      */
// 
//     public Iterable<LocationDto> search(String query) {
//         String path = WEATHER_HOST + WEATHER_SEARCH + WEATHER_SEARCH_ARGS;
//         String url = String.format(path, query, WEATHER_TOKEN);
//         Iterable<String> content = () -> req.getContent(url).iterator();
//         Iterable<String> iterable =	filter(content, (String s) -> !s.startsWith("#"));
//         return map(iterable, LocationDto::valueOf);
//     }
// 
//     /**
//      * E.g. http://api.worldweatheronline.com/free/v2/search.ashx?query=oporto&format=tab&key=*****
//      */
//     public Iterable<WeatherInfoDto> pastWeather(
//             double lat,
//             double log,
//             LocalDate from,
//             LocalDate to
//     ) {
//         String query = lat + "," + log;
//         String path = WEATHER_HOST + WEATHER_PAST +
//                 String.format(WEATHER_PAST_ARGS, query, from, to, WEATHER_TOKEN);
//         Iterable<String> content = () -> req.getContent(path).iterator();
//         Iterable<String> stringIterable = filter(content, s->!s.startsWith("#"));
//         Iterable<String>filtered = skip(stringIterable,1);	//  Skip line: Not Available
//         int[] counter = {0};
//         Predicate<String> isEvenLine = item -> ++counter[0] % 2==0;
//         filtered = filter(filtered,isEvenLine);//even lines filter
//         return map(filtered, WeatherInfoDto::valueOf); //to weatherinfo objects
//     }
// }
// 
// Path: aula33-weather-async/src/main/java/weather/model/WeatherInfo.java
// public class WeatherInfo {
//     private final LocalDate date;
//     private final int tempC;
//     private final String description;
//     private final double  precipMM;
//     private final int feelsLikeC;
// 
//     public WeatherInfo(LocalDate date, int tempC, String description, double precipMM, int feelsLikeC) {
//         this.date = date;
//         this.tempC = tempC;
//         this.description = description;
//         this.precipMM = precipMM;
//         this.feelsLikeC = feelsLikeC;
//     }
// 
//     public LocalDate getDate() {
//         return date;
//     }
// 
//     public int getTempC() {
//         return tempC;
//     }
// 
//     public String getDescription() {
//         return description;
//     }
// 
//     public double getPrecipMM() {
//         return precipMM;
//     }
// 
//     public int getFeelsLikeC() {
//         return feelsLikeC;
//     }
// 
//     @Override
//     public String toString() {
//         return "WeatherInfo{" +
//                 "date=" + date +
//                 ", tempC=" + tempC +
//                 ", description='" + description + '\'' +
//                 ", precipMM=" + precipMM +
//                 ", feelsLikeC=" + feelsLikeC +
//                 '}';
//     }
// }


import weather.data.WeatherWebApi;
import weather.model.WeatherInfo;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.*;
/*
 * Copyright (c) 2017, Miguel Gamboa
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package weather;





/**
 * @author Miguel Gamboa
 *         created on 18-04-2017
 */
public class WeatherServiceCache extends WeatherService{

    public WeatherServiceCache(WeatherWebApi api) {
        super(api);
    }

// Path: aula21-iterator-vs-stream/src/main/java/weather/data/WeatherWebApi.java
// public class WeatherWebApi {
// 
//     private static final String WEATHER_TOKEN;
//     private static final String WEATHER_HOST = "http://api.worldweatheronline.com";
//     private static final String WEATHER_PAST = "/premium/v1/past-weather.ashx";
//     private static final String WEATHER_PAST_ARGS =
//             "?q=%s&date=%s&enddate=%s&tp=24&format=csv&key=%s";
//     private static final String WEATHER_SEARCH="/premium/v1/search.ashx?query=%s";
//     private static final String WEATHER_SEARCH_ARGS="&format=tab&key=%s";
// 
//     static {
//         try {
//             URL keyFile = ClassLoader.getSystemResource("worldweatheronline-app-key.txt");
//             if(keyFile == null) {
//                throw new IllegalStateException(
//                        "YOU MUST GOT a KEY in developer.worldweatheronline.com and place it in src/main/resources/worldweatheronline-app-key.txt");
//             } else {
//                 InputStream keyStream = keyFile.openStream();
//                 try (BufferedReader reader = new BufferedReader(new InputStreamReader(keyStream))) {
//                     WEATHER_TOKEN = reader.readLine();
//                 }
//             }
//         } catch (IOException e) {
//             throw new UncheckedIOException(e);
//         }
//     }
// 
//     private final IRequest req;
// 
//     public WeatherWebApi(IRequest req) {
//         this.req = req;
//     }
// 
//     /**
//      * E.g. http://api.worldweatheronline.com/free/v2/search.ashx?query=oporto&format=tab&key=*****
//      */
// 
//     public Iterable<LocationDto> search(String query) {
//         String path = WEATHER_HOST + WEATHER_SEARCH + WEATHER_SEARCH_ARGS;
//         String url = String.format(path, query, WEATHER_TOKEN);
//         Iterable<String> content = () -> req.getContent(url).iterator();
//         Iterable<String> iterable =	filter(content, (String s) -> !s.startsWith("#"));
//         return map(iterable, LocationDto::valueOf);
//     }
// 
//     /**
//      * E.g. http://api.worldweatheronline.com/free/v2/search.ashx?query=oporto&format=tab&key=*****
//      */
//     public Iterable<WeatherInfoDto> pastWeather(
//             double lat,
//             double log,
//             LocalDate from,
//             LocalDate to
//     ) {
//         String query = lat + "," + log;
//         String path = WEATHER_HOST + WEATHER_PAST +
//                 String.format(WEATHER_PAST_ARGS, query, from, to, WEATHER_TOKEN);
//         Iterable<String> content = () -> req.getContent(path).iterator();
//         Iterable<String> stringIterable = filter(content, s->!s.startsWith("#"));
//         Iterable<String>filtered = skip(stringIterable,1);	//  Skip line: Not Available
//         int[] counter = {0};
//         Predicate<String> isEvenLine = item -> ++counter[0] % 2==0;
//         filtered = filter(filtered,isEvenLine);//even lines filter
//         return map(filtered, WeatherInfoDto::valueOf); //to weatherinfo objects
//     }
// }
// 
// Path: aula33-weather-async/src/main/java/weather/model/WeatherInfo.java
// public class WeatherInfo {
//     private final LocalDate date;
//     private final int tempC;
//     private final String description;
//     private final double  precipMM;
//     private final int feelsLikeC;
// 
//     public WeatherInfo(LocalDate date, int tempC, String description, double precipMM, int feelsLikeC) {
//         this.date = date;
//         this.tempC = tempC;
//         this.description = description;
//         this.precipMM = precipMM;
//         this.feelsLikeC = feelsLikeC;
//     }
// 
//     public LocalDate getDate() {
//         return date;
//     }
// 
//     public int getTempC() {
//         return tempC;
//     }
// 
//     public String getDescription() {
//         return description;
//     }
// 
//     public double getPrecipMM() {
//         return precipMM;
//     }
// 
//     public int getFeelsLikeC() {
//         return feelsLikeC;
//     }
// 
//     @Override
//     public String toString() {
//         return "WeatherInfo{" +
//                 "date=" + date +
//                 ", tempC=" + tempC +
//                 ", description='" + description + '\'' +
//                 ", precipMM=" + precipMM +
//                 ", feelsLikeC=" + feelsLikeC +
//                 '}';
//     }
// }


// Path: aula31-weather-groupingBy/src/main/java/weather/WeatherServiceCache.java
import weather.data.WeatherWebApi;
import weather.model.WeatherInfo;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.*;

/*
 * Copyright (c) 2017, Miguel Gamboa
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package weather;





/**
 * @author Miguel Gamboa
 *         created on 18-04-2017
 */
public class WeatherServiceCache extends WeatherService{

    public WeatherServiceCache(WeatherWebApi api) {
        super(api);
    }

    private final Map<Coords, Map<LocalDate, WeatherInfo>> cache = new HashMap<>();