package org.openweathermap.api;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.openweathermap.api.gson.WindDirectionDeserializer;
import org.openweathermap.api.gson.WindDirectionSerializer;
import org.openweathermap.api.model.WindDirection;
import org.openweathermap.api.model.currentweather.CurrentWeather;
import org.openweathermap.api.model.forecast.ForecastInformation;
import org.openweathermap.api.model.forecast.daily.DailyForecast;
import org.openweathermap.api.model.forecast.hourly.HourlyForecast;
import org.openweathermap.api.model.uvi.Uvi;
import org.openweathermap.api.query.Query;
import org.openweathermap.api.query.QueryWithResponseFormat;
import org.openweathermap.api.query.ResponseFormat;
import org.openweathermap.api.query.currentweather.CurrentWeatherMultipleLocationsQuery;
import org.openweathermap.api.query.currentweather.CurrentWeatherOneLocationQuery;
import org.openweathermap.api.query.forecast.daily.DailyForecastQuery;
import org.openweathermap.api.query.forecast.hourly.HourlyForecastQuery;
import org.openweathermap.api.query.uvi.current.CurrentUviQuery;
import org.openweathermap.api.query.uvi.forecast.ForecastUviQuery;
import org.openweathermap.api.query.uvi.history.HistoryUviQuery;

import java.lang.reflect.Type;
import java.util.List;


public abstract class AbstractDataWeatherClient implements DataWeatherClient {
    private final Gson gson = new GsonBuilder()
            .registerTypeAdapter(WindDirection.class, new WindDirectionDeserializer())
            .registerTypeAdapter(WindDirection.class, new WindDirectionSerializer())
            .create();

    @Override
    public ForecastInformation<HourlyForecast> getForecastInformation(HourlyForecastQuery query) {
        ForecastInformation<HourlyForecast> result = getResult(query, HourlyForecast.TYPE);
        return result;
    }

    @Override
    public ForecastInformation<DailyForecast> getForecastInformation(DailyForecastQuery query) {
        ForecastInformation<DailyForecast> result = getResult(query, DailyForecast.TYPE);
        return result;
    }

    @Override
    public String getWeatherData(Query query) {
        return makeRequest(query);
    }


    @Override
    public CurrentWeather getCurrentWeather(CurrentWeatherOneLocationQuery query) {
        CurrentWeather result = getResult(query, CurrentWeather.TYPE);
        return result;
    }

    @Override
    public List<CurrentWeather> getCurrentWeather(CurrentWeatherMultipleLocationsQuery query) {
        List<CurrentWeather> result = getResult(query, CurrentWeather.TYPE_LIST);
        return result;
    }

    @Override
    public Uvi getCurrentUvi(CurrentUviQuery query) {
        Uvi result = getResult(query, Uvi.TYPE);
        return result;
    }

    @Override
    public List<Uvi> getUviForecast(ForecastUviQuery query) {
        List<Uvi> result = getResult(query, Uvi.TYPE_LIST);
        return result;
    }

    @Override
    public List<Uvi> getUviHistory(HistoryUviQuery query) {
        List<Uvi> result = getResult(query, Uvi.TYPE_LIST);
        return result;
    }

    protected abstract String makeRequest(Query query);

    private <T> T getResult(QueryWithResponseFormat query, Type type) {
        ResponseFormat responseFormat = query.getResponseFormat();
        if (responseFormat == null || responseFormat == ResponseFormat.JSON) {
            return getResult((Query) query, type);
        }
        return null;
    }

    private <T> T getResult(Query query, Type type) {
        String data = getWeatherData(query);
        final T result = gson.fromJson(data, type);
        return result;
    }
}

@@ -53,48 +53,9 @@
 son.
-Gson;%0Aimport com.google.gson.GsonBuilder
+*
 ;%0Aim
@@ -1345,251 +1345,8 @@
 nt %7B
-%0A    private final Gson gson = new GsonBuilder()%0A            .registerTypeAdapter(WindDirection.class, new WindDirectionDeserializer())%0A            .registerTypeAdapter(WindDirection.class, new WindDirectionSerializer())%0A            .create();
 %0A%0A  
@@ -2215,32 +2215,213 @@
 sQuery query) %7B%0A
+        String data = getWeatherData(query);%0A        JsonObject jsonObject = jsonParser().parse(data).getAsJsonObject();%0A        JsonArray list = jsonObject.getAsJsonArray(%22list%22);%0A
         List%3CCur
@@ -2439,38 +2439,43 @@
 %3E result = g
-etResult(query
+son().fromJson(list
 , CurrentWea
@@ -3490,16 +3490,18 @@
 t = gson
+()
 .fromJso
@@ -3543,11 +3543,824 @@
 t;%0A    %7D
+%0A%0A    protected static Gson gson() %7B%0A        return GsonHolder.INSTANCE.value;%0A    %7D%0A%0A    protected static JsonParser jsonParser() %7B%0A        return JsonParserHolder.INSTANCE.value;%0A    %7D%0A%0A    private enum JsonParserHolder %7B%0A        INSTANCE;%0A%0A        @SuppressWarnings(%7B%22NonSerializableFieldInSerializableClass%22, %22ImmutableEnumChecker%22%7D)%0A        private final JsonParser value = new JsonParser();%0A%0A    %7D%0A%0A    private enum GsonHolder %7B%0A        INSTANCE;%0A        @SuppressWarnings(%7B%22NonSerializableFieldInSerializableClass%22, %22ImmutableEnumChecker%22%7D)%0A        private final Gson value = new GsonBuilder()%0A                .registerTypeAdapter(WindDirection.class, new WindDirectionDeserializer())%0A                .registerTypeAdapter(WindDirection.class, new WindDirectionSerializer())%0A                .create();%0A    %7D
 %0A%7D%0A

Make sure CurrentWeather is fetched correctly for multiple cities.