package de.apps4ics.mountainnavigation.handlers;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.Log;
import com.survivingwithandroid.weather.lib.WeatherClient;
import com.survivingwithandroid.weather.lib.WeatherCode;
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.DayForecast;
import com.survivingwithandroid.weather.lib.model.HistoricalHourWeather;
import com.survivingwithandroid.weather.lib.model.HistoricalWeather;
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.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import de.apps4ics.mountainnavigation.InformDialog;
import de.apps4ics.mountainnavigation.InformListDialog;
import de.apps4ics.mountainnavigation.MainActivity;
import de.apps4ics.mountainnavigation.MyWeather;
import de.apps4ics.mountainnavigation.R;
import de.apps4ics.mountainnavigation.WeatherDatabase;
import de.apps4ics.mountainnavigation.adapters.WarningListAdapter;
/**
* Created by Vinz on 06.03.2016.
*/
public class WeatherHandler {
private static final String API_KEY = "fd4034defae557fd5f2fdaaf73c3402c"; //OpenWeatherMap API Key
private Context context;
private WeatherDatabase weatherDb;
private WeatherClient weatherClient;
private HistoricalWeather histWeather;
private DayForecast[] forecasts;
private Weather[] weathers;
private final static float MIN_HOT_TEMP_DEFAULT = 30.0f;
private final static float MAX_COLD_TEMP_DEFAULT = 10.0f;
private final static int MAX_DAYS_FORECAST_DEFAULT = 3;
private static float MIN_HOT_TEMP;
private static float MAX_COLD_TEMP;
private static int MAX_DAYS_FORECAST;
private static float MIN_WINDY_SPEED;
private static Activity activity;
private static FragmentManager fragmentManager;
public WeatherHandler(Context context) {
weatherDb = new WeatherDatabase(context);
this.context = context;
try {
activity = (Activity) context;
fragmentManager = activity.getFragmentManager();
} catch(ClassCastException e) {
Log.e(MainActivity.TAG, "Could not get fragment manager!");
//TODO close app?
}
Resources res = MainActivity.getRes();
SharedPreferences sharedPrefs = MainActivity.getSharedPrefs();
MAX_DAYS_FORECAST = Integer.parseInt(MainActivity.getSharedPrefs().getString(
res.getString(R.string.settings_weather_days_forecast),
String.valueOf(MAX_DAYS_FORECAST_DEFAULT)));
WeatherClient.ClientBuilder weatherBuilder = new WeatherClient.ClientBuilder();
WeatherConfig weatherConfig = new WeatherConfig();
weatherConfig.unitSystem = WeatherConfig.UNIT_SYSTEM.M;
weatherConfig.ApiKey = API_KEY;
weatherConfig.lang = res.getString(R.string.lang_identifier);
weatherConfig.numDays = MAX_DAYS_FORECAST;
MIN_HOT_TEMP = Float.parseFloat(sharedPrefs.getString(res.getString(R.string.settings_hint_min_hot_temp_key), String.valueOf(MIN_HOT_TEMP_DEFAULT)));
MAX_COLD_TEMP = Float.parseFloat(sharedPrefs.getString(res.getString(R.string.settings_hint_max_cold_temp_key), String.valueOf(MAX_COLD_TEMP_DEFAULT)));
MIN_WINDY_SPEED = 8; //http://www.wettergefahren-fruehwarnung.de/Artikel/beaufort.html
if(weatherConfig.unitSystem.equals(WeatherConfig.UNIT_SYSTEM.I)){
MIN_HOT_TEMP = celsiusToFahrenheit(MIN_HOT_TEMP);
MAX_COLD_TEMP = celsiusToFahrenheit(MAX_COLD_TEMP);
}
weatherClient = null;
try {
weatherClient = weatherBuilder.attach(context)
.provider(new OpenweathermapProviderType())
.httpClient(com.survivingwithandroid.weather.lib.client.okhttp.WeatherDefaultClient.class)
.config(weatherConfig)
.build();
} catch (WeatherProviderInstantiationException e) {
e.printStackTrace();
}
}
/**
*
* @param offset number of days (in the past) to search for result in the cache, only for getCurrentWeatherCached
*/
public MyWeather getCurrentWeather(double lat, double lon, int offset) {
if(MainActivity.hasInternet()) return getCurrentWeatherOnline(lat, lon);
else return getCurrentWeatherCached(lat, lon, offset);
}
//TODO
private MyWeather getCurrentWeatherOnline(double lat, double lon) {
//return new MyWeather();
return null;
}
//TODO
private MyWeather getCurrentWeatherCached(double lat, double lon, int offset) {
//return new MyWeather();
return null;
}
public List<MyWeather> getForecast(double lat, double lon) {
return getForecast(lat, lon, MAX_DAYS_FORECAST, 0);
}
public List<MyWeather> getForecast(double lat, double lon, int days, int offset) {
if(MainActivity.hasInternet()) return getForecastOnline(lat, lon, days);
else return getForecastCached(lat, lon, days, offset);
}
public List<MyWeather> getForecastOnline(double lat, double lon, final int days) {
final List<MyWeather> weatherList = new ArrayList<>();
weatherClient.getForecastWeather(new WeatherRequest(lon, lat), new WeatherClient.ForecastWeatherEventListener() {
@Override
public void onWeatherRetrieved(WeatherForecast forecast) {
List<DayForecast> foundForecasts = forecast.getForecast();
if(foundForecasts.size() == 0) return;
int dayCount = Math.min(foundForecasts.size(), days);
forecasts = new DayForecast[dayCount];
weathers = new Weather[dayCount];
for(int i=0; i<dayCount; i++) {
DayForecast curr = foundForecasts.get(i);
forecasts[i] = curr;
weathers[i] = curr.weather;
weatherList.add(new MyWeather(curr));
}
Log.d(MainActivity.TAG, "City [" + weathers[0].location.getCity() + "] Current temp: " + weathers[0].temperature.getTemp());
String title = String.format("Weather for %s in %s", weathers[0].location.getCity(), weathers[0].location.getCountry());
String msg = String.format("%1$.1f%2$s (%3$.1f%4$s/%5$.1f%6$s)\nSunrise: %7$s\nSunset: %8$s\nWeatherCode: %9$d\nWeatherId: %10$d",
forecasts[0].forecastTemp.day,
forecast.getUnit().tempUnit,
forecasts[0].forecastTemp.min,
forecast.getUnit().tempUnit,
forecasts[0].forecastTemp.max,
forecast.getUnit().tempUnit,
MainActivity.df_hm.format(new Date(weathers[0].location.getSunrise() * 1000)),
MainActivity.df_hm.format(new Date(weathers[0].location.getSunset() * 1000)),
weathers[0].currentCondition.getWeatherCode().getCode(),
weathers[0].currentCondition.getWeatherId());
Log.d(MainActivity.TAG, title + ": " + msg);
displayHints(weatherList.get(0));
displaySevereWeather(weatherList.get(0));
}
@Override
public void onWeatherError(WeatherLibException wle) {
Log.e(MainActivity.TAG, "Weather error - parsing data");
wle.printStackTrace();
}
@Override
public void onConnectionError(Throwable t) {
Log.e(MainActivity.TAG, "Connection Error");
t.printStackTrace();
}
});
return weatherList;
}
//TODO
public List<MyWeather> getForecastCached(double lat, double lon, int days, int offset) {
return null;
}
public List<MyWeather> getHistoricalWeather(float lat, float lon, long start, long end){
if(MainActivity.hasInternet()) return getHistoricalWeatherOnline(lat, lon, start, end);
else return getHistoricalWeatherCached(lat, lon, start, end);
}
public List<MyWeather> getHistoricalWeatherOnline(float lat, float lon, long start, long end) {
ArrayList<MyWeather> weathers = new ArrayList<>();
Date startDate = new Date(start / 1000); //OWM uses seconds instead of milliseconds
Date endDate = new Date(end / 1000);
histWeather = null;
weatherClient.getHistoricalWeather(new WeatherRequest(lon, lat), startDate, endDate, new WeatherClient.HistoricalWeatherEventListener() {
@Override
public void onWeatherRetrieved(HistoricalWeather historicalWeather) {
//TODO check if it was sunny/rainy and set fountain options based on this
histWeather = historicalWeather;
}
@Override
public void onWeatherError(WeatherLibException wle) {
Log.e(MainActivity.TAG, "Weather error - parsing data");
wle.printStackTrace();
}
@Override
public void onConnectionError(Throwable t) {
Log.e(MainActivity.TAG, "Connection Error");
t.printStackTrace();
}
});
for(HistoricalHourWeather hhw : histWeather.getHoistoricalData()) {
weathers.add(new MyWeather(hhw.weather, hhw.timestamp));
}
return weathers;
}
private List<MyWeather> getHistoricalWeatherCached(float lat, float lon, long start, long end) {
return null;
}
private void insertIntoDatabase(Weather weather) {
insertIntoDatabase(weather, 0);
}
private void insertIntoDatabase(Weather weather, long timestamp) {
insertIntoDatabase(new MyWeather(weather, timestamp));
}
private void insertIntoDatabase(MyWeather weather) {
weatherDb.insertWeather(weather);
}
private void displayHints(MyWeather weather) {
//TODO add more hints
if (MainActivity.showWeatherHints()) {
Resources res = MainActivity.getRes();
List<String> titles = new ArrayList<>();
List<String> descs = new ArrayList<>();
List<String> infos = new ArrayList<>();
if (weather.isSunny()) {
titles.add(res.getString(R.string.hint_dialog_titles_sunny));
descs.add(res.getString(R.string.hint_dialog_msgs_sunny));
infos.add("");
}
if (weather.isHot()) {
titles.add(res.getString(R.string.hint_dialog_titles_hot));
descs.add(res.getString(R.string.hint_dialog_msgs_hot));
infos.add(res.getString(R.string.hint_dialog_info_hot));
}
if (weather.isCold()) {
titles.add(res.getString(R.string.hint_dialog_titles_cold));
descs.add(res.getString(R.string.hint_dialog_msgs_cold));
infos.add("");
}
if (weather.isWindy()) {
titles.add(res.getString(R.string.hint_dialog_titles_windy));
descs.add(res.getString(R.string.hint_dialog_msgs_windy));
infos.add("");
}
if (weather.isAfterSunset()) {
titles.add(res.getString(R.string.hint_dialog_titles_sunset));
descs.add(res.getString(R.string.hint_dialog_msgs_sunset));
infos.add("");
}
if (titles.size() > 0 && descs.size() > 0) {
String[] titleArr = new String[titles.size()];
String[] descArr = new String[descs.size()];
String[] infosArr = new String[infos.size()];
titleArr = titles.toArray(titleArr);
descArr = descs.toArray(descArr);
infosArr = infos.toArray(infosArr);
WarningListAdapter warningAdapter = new WarningListAdapter(activity, titleArr, descArr, infosArr);
InformListDialog weatherHintDialog = new InformListDialog(MainActivity.getRes().getString(R.string.hint_dialog_title), warningAdapter);
weatherHintDialog.show(fragmentManager, "Warning Hint Dialog");
}
}
}
private void displaySevereWeather(MyWeather weather) {
if (weather.isSevereWeather(weather.getWeatherCode())) {
Log.d(MainActivity.TAG, "It is severe weather! :(");
Resources res = context.getResources();
String warnMsg = String.format(res.getString(R.string.weather_warning_dialog_msg), weather.getCity(), weather.getWeatherCode());
InformDialog informAlertDialog = new InformDialog(res.getString(R.string.weather_warning_dialog_title), warnMsg);
informAlertDialog.show(fragmentManager, "Inform Dialog - Weather Warning");
}
}
public static float getMinHotTemp() {
return MIN_HOT_TEMP;
}
public static float getMinWindySpeed() {
return MIN_WINDY_SPEED;
}
public static int getMaxDaysForecast() {
return MAX_DAYS_FORECAST;
}
public static float getMaxColdTemp() {
return MAX_COLD_TEMP;
}
public static float celsiusToFahrenheit(float c) {
return c * 9.0f/5.0f + 32;
}
public static float fahrenheitToCelsius(float f) {
return (f - 32.0f) * 5.0f/9.0f;
}
}