package net.maxbraun.mirror;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
import java.util.Locale;
import net.maxbraun.mirror.Body.BodyMeasure;
import net.maxbraun.mirror.Commute.CommuteSummary;
import net.maxbraun.mirror.DataUpdater.UpdateListener;
import net.maxbraun.mirror.Weather.WeatherData;
/**
* The main {@link Activity} class and entry point into the UI.
*/
public class HomeActivity extends Activity {
/**
* The IDs of {@link TextView TextViews} in {@link R.layout#activity_home} which contain the news
* headlines.
*/
private static final int[] NEWS_VIEW_IDS = new int[]{
R.id.news_1,
R.id.news_2,
R.id.news_3,
R.id.news_4,
};
/**
* The listener used to populate the UI with weather data.
*/
private final UpdateListener<WeatherData> weatherUpdateListener =
new UpdateListener<WeatherData>() {
@Override
public void onUpdate(WeatherData data) {
if (data != null) {
// Populate the current temperature rounded to a whole number.
String temperature = String.format(Locale.US, "%d°",
Math.round(getLocalizedTemperature(data.currentTemperature)));
temperatureView.setText(temperature);
// Populate the 24-hour forecast summary, but strip any period at the end.
String summary = util.stripPeriod(data.daySummary);
weatherSummaryView.setText(summary);
// Populate the precipitation probability as a percentage rounded to a whole number.
String precipitation =
String.format(Locale.US, "%d%%", Math.round(100 * data.dayPrecipitationProbability));
precipitationView.setText(precipitation);
// Populate the icon for the current weather.
iconView.setImageResource(data.currentIcon);
// Show all the views.
temperatureView.setVisibility(View.VISIBLE);
weatherSummaryView.setVisibility(View.VISIBLE);
precipitationView.setVisibility(View.VISIBLE);
iconView.setVisibility(View.VISIBLE);
} else {
// Hide everything if there is no data.
temperatureView.setVisibility(View.GONE);
weatherSummaryView.setVisibility(View.GONE);
precipitationView.setVisibility(View.GONE);
iconView.setVisibility(View.GONE);
}
}
};
/**
* The listener used to populate the UI with news headlines.
*/
private final UpdateListener<List<String>> newsUpdateListener =
new UpdateListener<List<String>>() {
@Override
public void onUpdate(List<String> headlines) {
// Populate the views with as many headlines as we have and hide the others.
for (int i = 0; i < NEWS_VIEW_IDS.length; i++) {
if ((headlines != null) && (i < headlines.size())) {
newsViews[i].setText(headlines.get(i));
newsViews[i].setVisibility(View.VISIBLE);
} else {
newsViews[i].setVisibility(View.GONE);
}
}
}
};
/**
* The listener used to populate the UI with body measurements.
*/
private final UpdateListener<BodyMeasure[]> bodyUpdateListener =
new UpdateListener<BodyMeasure[]>() {
@Override
public void onUpdate(BodyMeasure[] bodyMeasures) {
if (bodyMeasures != null) {
bodyView.setBodyMeasures(bodyMeasures);
bodyView.setVisibility(View.VISIBLE);
} else {
bodyView.setVisibility(View.GONE);
}
}
};
/**
* The listener used to populate the UI with the commute summary.
*/
private final UpdateListener<CommuteSummary> commuteUpdateListener =
new UpdateListener<CommuteSummary>() {
@Override
public void onUpdate(CommuteSummary summary) {
if (summary != null) {
commuteTextView.setText(summary.text);
commuteTextView.setVisibility(View.VISIBLE);
travelModeView.setImageDrawable(summary.travelModeIcon);
travelModeView.setVisibility(View.VISIBLE);
if (summary.trafficTrendIcon != null) {
trafficTrendView.setImageDrawable(summary.trafficTrendIcon);
trafficTrendView.setVisibility(View.VISIBLE);
} else {
trafficTrendView.setVisibility(View.GONE);
}
} else {
commuteTextView.setVisibility(View.GONE);
travelModeView.setVisibility(View.GONE);
trafficTrendView.setVisibility(View.GONE);
}
}
};
private TextView temperatureView;
private TextView weatherSummaryView;
private TextView precipitationView;
private ImageView iconView;
private TextView[] newsViews = new TextView[NEWS_VIEW_IDS.length];
private BodyView bodyView;
private TextView commuteTextView;
private ImageView travelModeView;
private ImageView trafficTrendView;
private Weather weather;
private News news;
private Body body;
private Commute commute;
private Util util;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
temperatureView = (TextView) findViewById(R.id.temperature);
weatherSummaryView = (TextView) findViewById(R.id.weather_summary);
precipitationView = (TextView) findViewById(R.id.precipitation);
iconView = (ImageView) findViewById(R.id.icon);
for (int i = 0; i < NEWS_VIEW_IDS.length; i++) {
newsViews[i] = (TextView) findViewById(NEWS_VIEW_IDS[i]);
}
bodyView = (BodyView) findViewById(R.id.body);
commuteTextView = (TextView) findViewById(R.id.commuteText);
travelModeView = (ImageView) findViewById(R.id.travelMode);
trafficTrendView = (ImageView) findViewById(R.id.trafficTrend);
weather = new Weather(this, weatherUpdateListener);
news = new News(newsUpdateListener);
body = new Body(this, bodyUpdateListener);
commute = new Commute(this, commuteUpdateListener);
util = new Util(this);
}
@Override
protected void onStart() {
super.onStart();
weather.start();
news.start();
body.start();
commute.start();
}
@Override
protected void onStop() {
weather.stop();
news.stop();
body.stop();
commute.stop();
super.onStop();
}
@Override
protected void onResume() {
super.onResume();
util.hideNavigationBar(temperatureView);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
return util.onKeyUp(keyCode, event);
}
/**
* Converts a temperature in degrees Fahrenheit to degrees Celsius, depending on the
* {@link Locale}.
*/
private double getLocalizedTemperature(double temperatureFahrenheit) {
// First approximation: Fahrenheit for US and Celsius anywhere else.
return Locale.US.equals(Locale.getDefault()) ?
temperatureFahrenheit : (temperatureFahrenheit - 32.0) / 1.8;
}
}