package com.novoda.magicmirror.modules.weather;
import android.content.Context;
import android.support.annotation.NonNull;
import com.novoda.magicmirror.BuildConfig;
import com.novoda.magicmirror.modules.DashboardModule;
import com.novoda.notils.logger.simple.Log;
import com.survivingwithandroid.weather.lib.WeatherClient;
import com.survivingwithandroid.weather.lib.WeatherConfig;
import com.survivingwithandroid.weather.lib.exception.WeatherLibException;
import com.survivingwithandroid.weather.lib.exception.WeatherProviderInstantiationException;
import com.survivingwithandroid.weather.lib.model.CurrentWeather;
import com.survivingwithandroid.weather.lib.model.DayForecast;
import com.survivingwithandroid.weather.lib.model.Weather;
import com.survivingwithandroid.weather.lib.model.WeatherForecast;
import com.survivingwithandroid.weather.lib.provider.openweathermap.OpenweathermapProviderType;
import com.survivingwithandroid.weather.lib.request.WeatherRequest;
import java.util.concurrent.TimeUnit;
public class WeatherModule implements DashboardModule {
private static final long MIN_UPDATE_DELAY = TimeUnit.MINUTES.toMillis(10);
private static final String API_KEY = BuildConfig.OPEN_WEATHER_MAP_KEY;
private static final double LIVERPOOL_LONGITUDE = -2.9982376;
private static final double LIVERPOOL_LATITUDE = 53.4097205;
private final WeatherClient client;
private final WeatherListener weatherListener;
private long lastUpdate = 0;
public static DashboardModule newInstance(Context context, WeatherListener weatherListener) {
WeatherClient.ClientBuilder builder = new WeatherClient.ClientBuilder();
WeatherConfig config = buildWeatherConfig();
try {
WeatherClient client = builder.attach(context)
.provider(new OpenweathermapProviderType())
.httpClient(com.survivingwithandroid.weather.lib.client.okhttp.WeatherDefaultClient.class)
.config(config)
.build();
return new WeatherModule(client, weatherListener);
} catch (WeatherProviderInstantiationException e) {
Log.e(e, "Error creating weather client");
return new DisabledWeatherModule(weatherListener);
}
}
@NonNull
private static WeatherConfig buildWeatherConfig() {
WeatherConfig config = new WeatherConfig();
config.unitSystem = WeatherConfig.UNIT_SYSTEM.M;
config.lang = "en";
config.maxResult = 5;
config.numDays = 6;
config.ApiKey = API_KEY;
return config;
}
public WeatherModule(WeatherClient client, WeatherListener weatherListener) {
this.client = client;
this.weatherListener = weatherListener;
}
@Override
public void update() {
if (tooCloseToLastUpdate()) {
return;
}
lastUpdate = System.currentTimeMillis();
// TODO: get current devicePosition
double longitude = LIVERPOOL_LONGITUDE;
double latitude = LIVERPOOL_LATITUDE;
WeatherRequest request = new WeatherRequest(longitude, latitude);
client.getCurrentCondition(request, new CurrentWeatherListener(weatherListener));
client.getForecastWeather(request, new TodayForecastListener(weatherListener));
}
private boolean tooCloseToLastUpdate() {
long now = System.currentTimeMillis();
return now - lastUpdate < MIN_UPDATE_DELAY;
}
private static class CurrentWeatherListener implements WeatherClient.WeatherEventListener {
private final WeatherListener weatherListener;
private CurrentWeatherListener(WeatherListener weatherListener) {
this.weatherListener = weatherListener;
}
@Override
public void onWeatherRetrieved(CurrentWeather weather) {
Weather.Temperature temperature = weather.weather.temperature;
WeatherInfo currentWeather = new WeatherInfo(
temperature.getTemp(),
temperature.getMinTemp(),
temperature.getMaxTemp(),
weather.weather.currentCondition.getCondition(),
weather.weather.currentCondition.getIcon());
weatherListener.onCurrentWeatherFetched(currentWeather);
}
@Override
public void onWeatherError(WeatherLibException e) {
Log.e(e, "Error while fetching weather conditions");
weatherListener.onCurrentWeatherUnavailable();
}
@Override
public void onConnectionError(Throwable e) {
Log.e(e, "Connection error while fetching weather conditions");
weatherListener.onCurrentWeatherUnavailable();
}
}
private static class TodayForecastListener implements WeatherClient.ForecastWeatherEventListener {
private final WeatherListener weatherListener;
private TodayForecastListener(WeatherListener weatherListener) {
this.weatherListener = weatherListener;
}
@Override
public void onWeatherRetrieved(WeatherForecast forecast) {
DayForecast todayForecast = forecast.getForecast(0);
WeatherInfo todayWeather = new WeatherInfo(
todayForecast.forecastTemp.day,
todayForecast.forecastTemp.min,
todayForecast.forecastTemp.max,
todayForecast.weather.currentCondition.getCondition(),
todayForecast.weather.currentCondition.getIcon()
);
weatherListener.onTodayForecastFetched(todayWeather);
}
@Override
public void onWeatherError(WeatherLibException e) {
Log.e(e, "Error while fetching weather forecast");
weatherListener.onTodayForecastUnavailable();
}
@Override
public void onConnectionError(Throwable e) {
Log.e(e, "Error while fetching weather forecast");
weatherListener.onTodayForecastUnavailable();
}
}
@Override
public void stop() {
// no-op
}
public interface WeatherListener {
void onCurrentWeatherFetched(WeatherInfo currentInfo);
void onTodayForecastFetched(WeatherInfo todayInfo);
void onCurrentWeatherUnavailable();
void onTodayForecastUnavailable();
}
}