package de.apps4ics.mountainnavigation;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.provider.Settings;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.GravityCompat;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.widget.DrawerLayout;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
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.provider.openweathermap.OpenweathermapProviderType;
import com.survivingwithandroid.weather.lib.request.WeatherRequest;
import org.osmdroid.api.IMapController;
import org.osmdroid.bonuspack.overlays.Marker;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Overlay;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements LocationListener {
public static final String TAG = "MountainNavigation";
/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
/**
* Used to store the last screen title. For use in {@link #restoreActionBar()}.
*/
private CharSequence mTitle;
private CharSequence mDrawerTitle;
private static final int GPS_MIN_TIME = 5000;
private static final int GPS_MIN_DIST = 5;
private Resources res;
private FloatingActionButton fab;
private WeatherClient weatherClient;
private DatabaseHandler dbHandler;
private MapView mapView;
private IMapController mapController;
private int ZOOM_LEVEL;
private ActionBarDrawerToggle drawerToggle;
private String[] fountainSizes;
private String[] pathOptions;
private String[] pathDescs;
private Integer[] pathOptionImgs;
private String[] breakPointOptions;
private Integer[] breakPointOptionsImgs;
private String[] entries;
private Integer[] entryImgs;
private Integer[] fountainImgs;
private DrawerLayout drawerLayout;
private ListView listView;
private List<Marker>[] poiMarkers;
private String provider;
private Location mLocation;
private LocationManager locationManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
res = getResources();
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.container);
dbHandler = new DatabaseHandler(this);
ZOOM_LEVEL = 18;
mapView = new MapView(getApplicationContext(), 256);
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
mapController = mapView.getController();
mapController.setZoom(ZOOM_LEVEL);
mapController.setCenter(new GeoPoint(48.52, 9.055));
poiMarkers = new List[Types.SIZE];
for(int i=0; i<poiMarkers.length; ++i){
poiMarkers[i] = new ArrayList<>();
}
relativeLayout.addView(mapView);
mTitle = mDrawerTitle = getTitle();
initGps();
fountainSizes = getResources().getStringArray(R.array.fountain_size_dialog_options);
fountainImgs = new Integer[]{
R.drawable.fountain_size_small,
R.drawable.fountain_size_medium,
R.drawable.fountain_size_big,
};
pathDescs = res.getStringArray(R.array.path_dialog_descs);
pathOptions = res.getStringArray(R.array.path_dialog_options);
pathOptionImgs = new Integer[]{
R.mipmap.path_exposed,
R.mipmap.path_difficult_wet,
R.mipmap.path_giddiness,
R.mipmap.path_climbing
};
breakPointOptions = res.getStringArray(R.array.break_point_dialog_options);
breakPointOptionsImgs = new Integer[]{
R.mipmap.ic_rock,
R.mipmap.ic_bench,
R.mipmap.ic_table,
R.mipmap.ic_roofed
};
entries = res.getStringArray(R.array.toggleEntries);
entryImgs = new Integer[]{
R.drawable.water,
R.drawable.path,
R.drawable.break_point,
R.drawable.trash,
R.drawable.image_upload,
R.drawable.cell_reception,
R.drawable.wifi,
R.drawable.lift
};
WeatherClient.ClientBuilder weatherBuilder = new WeatherClient.ClientBuilder();
WeatherConfig weatherConfig = new WeatherConfig();
weatherConfig.unitSystem = WeatherConfig.UNIT_SYSTEM.M;
weatherClient = null;
try {
weatherClient = weatherBuilder.attach(getApplicationContext())
.provider(new OpenweathermapProviderType())
.httpClient(com.survivingwithandroid.weather.lib.client.okhttp.WeatherDefaultClient.class)
.config(weatherConfig)
.build();
} catch (WeatherProviderInstantiationException e) {
e.printStackTrace();
}
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mLocation == null){
InformDialog informDialog = new InformDialog(getString(R.string.inform_title), getString(R.string.inform_gps_pos_not_found));
informDialog.show(getFragmentManager(), "Inform Dialog");
return;
}
AddPoiDialog addPoiDialog = new AddPoiDialog();
addPoiDialog.show(getFragmentManager(), "Add POI Dialog");
}
});
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
listView = (ListView) findViewById(R.id.navigation_drawer);
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// listView.setItemsCanFocus(false);
ImageListAdapter adapter = new ImageListAdapter(MainActivity.this, entries, entryImgs);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TableLayout layout = (TableLayout) view;
toggleDrawerItems(layout, position);
}
});
drawerLayout.setDrawerListener(drawerToggle);
double _lat = 48.52;
double _lon = 9.055;
double _alt = 350;
int _type = Types.FOUNTAIN;
long _time = System.currentTimeMillis() / 1000;
Poi poi = new Poi(_lat, _lon, _alt, _type, _time);
dbHandler.addPoi(poi);
}
private void toggleDrawerItems(TableLayout layout, int position){
TableRow tr = (TableRow) layout.getChildAt(0); //TODO is tablerow?
TextView tv = null;
ImageView iv = null;
for(int i=0; i<tr.getChildCount(); ++i){
View v = tr.getChildAt(i);
try {
tv = (TextView) v;
} catch(ClassCastException cce){
//Log.e(TAG, "Could not cast " + v.getClass().toString() + " to TextView!");
}
try {
iv = (ImageView) v;
} catch(ClassCastException cce){
//Log.e(TAG, "Could not cast " + v.getClass().toString() + " to ImageView!");
}
}
if(tv == null || iv == null) Log.e(TAG, "Neither TextView nor ImageView can be null!");
int type = getType(position);
if(iv.getTag() == null || iv.getTag() == "disabled"){
iv.setColorFilter(null);
iv.setTag("");
//Typeface tf = Typeface.create("sans-serif-medium", Typeface.BOLD);
//tv.setTypeface(tf);
tv.setTextColor(res.getColor(R.color.text_color_selected));
Toaster("You enabled " + entries[position]);
String title = entries[position];
List<Poi> tempPoiList = dbHandler.getPoiByType(type);
for(int i=0; i<tempPoiList.size(); ++i){
Poi poi = tempPoiList.get(i);
GeoPoint gp = new GeoPoint(poi.getLat(), poi.getLon());
String snippetText = res.getString(R.string.osm_marker_snippet, gp.getLatitude(), gp.getLongitude(), gp.getAltitude());
String subDescText;
ArrayList<Properties> optList = dbHandler.getPoiOptions(poi.getId());
for(int j=0; j<optList.size(); ++j){
Properties prop = optList.get(j);
if(type == Types.FOUNTAIN) title += " (" + fountainSizes[(int)prop.get_opt_id()] + ")";
}
Marker positionMarker = new Marker(mapView);
positionMarker.setPosition(gp);
positionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
positionMarker.setTitle(title);
positionMarker.setSnippet(snippetText);
positionMarker.setImage(res.getDrawable(entryImgs[type]));
Drawable[] iconLayer = new Drawable[2];
iconLayer[0] = res.getDrawable(R.mipmap.ic_poi);
BitmapDrawable bd = (BitmapDrawable) res.getDrawable(entryImgs[type]);
Bitmap b = bd.getBitmap();
Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
bd = new BitmapDrawable(res, bResized);
bd.setGravity(Gravity.CENTER_HORIZONTAL);
iconLayer[1] = bd;
LayerDrawable icon = new LayerDrawable(iconLayer);
positionMarker.setIcon(icon);
mapView.getOverlays().add(positionMarker);
poiMarkers[type].add(positionMarker);
}
mapView.invalidate();
} else {
iv.setColorFilter(Color.argb(200, 185, 185, 185));
iv.setTag("disabled");
tv.setTextColor(res.getColor(R.color.text_color));
//Typeface tf = Typeface.create("sans-serif-medium", Typeface.NORMAL);
//tv.setTypeface(tf);
Toaster("You disabled " + entries[position]);
for(int i=0; i<poiMarkers[type].size(); ++i){
Overlay poi = poiMarkers[type].get(i);
mapView.getOverlays().remove(poi);
}
poiMarkers[type] = new ArrayList<>();
mapView.invalidate();
}
}
private int getType(int position){
int type;
switch (position){
case 0:
type = Types.FOUNTAIN;
break;
case 1:
type = Types.PATH;
break;
case 2:
type = Types.BREAK_POINT;
break;
case 3:
type = Types.TRASH_BIN;
break;
case 4:
type = Types.PIC;
break;
case 5:
type = Types.CELL_RECEPTION;
break;
case 6:
type = Types.WIFI;
break;
case 7:
type = Types.LIFT;
break;
default:
type = 0;
break;
}
return type;
}
private void initGps(){
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean isLocationEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(!isLocationEnabled){
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
mLocation = locationManager.getLastKnownLocation(provider);
}
private void Toaster(String text){
Toaster(text, false);
}
private void Toaster(String text, boolean longDuration){
if(longDuration) Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
else Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
private void addSimpleMarker(GeoPoint gp){
Marker positionMarker = new Marker(mapView);
positionMarker.setPosition(gp);
positionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
positionMarker.setTitle(getString(R.string.osm_marker_title));
positionMarker.setSnippet("Latitude: " + gp.getLatitude() + "\n" + "Longitude: " + gp.getLongitude());
mapView.getOverlays().add(positionMarker);
mapView.invalidate();
}
@Override
public void onLocationChanged(Location location) {
mLocation = location;
if(mLocation == null) return;
double lat = location.getLatitude();
double lon = location.getLongitude();
GeoPoint gp = new GeoPoint(lat, lon);
addSimpleMarker(gp);
mapController.setCenter(gp);
//TODO Move this to the not-yet-implemented upload method
weatherClient.getCurrentCondition(new WeatherRequest(lon, lat), new WeatherClient.WeatherEventListener() {
@Override
public void onWeatherRetrieved(CurrentWeather weather) {
Log.d(TAG, "City [" + weather.weather.location.getCity() + "] Current temp: " + weather.weather.temperature.getTemp());
}
@Override
public void onWeatherError(WeatherLibException wle) {
Log.e(TAG, "Weather error - parsing data");
wle.printStackTrace();
}
@Override
public void onConnectionError(Throwable t) {
Log.e(TAG, "Connection Error");
t.printStackTrace();
}
});
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
public class InformDialog extends DialogFragment {
private String title;
private String msg;
public InformDialog(String title, String msg){
this.title = title;
this.msg = msg;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(title)
.setMessage(msg)
.setCancelable(false)
.setIcon(res.getDrawable(R.mipmap.ic_info_icon))
.setPositiveButton(R.string.inform_positive_button, null);
return builder.create();
}
}
public class AddPoiDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.add_poi_dialog_title)
.setIcon(res.getDrawable(R.mipmap.ic_add_poi))
.setAdapter(new ImageListAdapter(MainActivity.this, entries, entryImgs), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int type = getType(which);
switch (type) {
case Types.FOUNTAIN:
AddFountainDialog addFountainDialog = new AddFountainDialog();
addFountainDialog.show(getFragmentManager(), "Add fountain POI Dialog");
break;
case Types.PATH:
AddPathDialog addPathDialog = new AddPathDialog();
addPathDialog.show(getFragmentManager(), "Add Path POI Dialog");
break;
case Types.BREAK_POINT:
AddBreakpointDialog addBreakpointDialog = new AddBreakpointDialog();
addBreakpointDialog.show(getFragmentManager(), "Add Break point POI Dialog");
break;
case Types.TRASH_BIN:
addPoi(Types.TRASH_BIN);
break;
case Types.PIC:
addPoi(Types.PIC);
break;
case Types.CELL_RECEPTION:
addPoi(Types.CELL_RECEPTION);
break;
case Types.WIFI:
addPoi(Types.WIFI);
break;
case Types.LIFT:
addPoi(Types.LIFT);
break;
}
}
});
return builder.create();
}
}
public class AddFountainDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.fountain_size_dialog_title)
.setIcon(res.getDrawable(R.drawable.water))
.setAdapter(new ImageListAdapter(MainActivity.this, fountainSizes, fountainImgs), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//Add POI to DB
int _type = Types.FOUNTAIN;
long rowId = addPoi(_type);
int size = 0;
switch (which) {
case 0:
size = Features.FOUNTAIN_SMALL;
break;
case 1:
size = Features.FOUNTAIN_MEDIUM;
break;
case 2:
size = Features.FOUNTAIN_LARGE;
break;
default:
Log.e(TAG, "Wrong fountain size " + which);
}
dbHandler.addPoiOptions(rowId, size);
}
});
return builder.create();
}
}
public class AddPathDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final List<Integer> mSelectedItems = new ArrayList<>();
final CheckboxImageAdapter adapter = new CheckboxImageAdapter(MainActivity.this, pathOptions, pathDescs, pathOptionImgs);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.path_dialog_title)
.setIcon(res.getDrawable(R.drawable.path))
.setPositiveButton(R.string.ok_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int[] options = adapter.getCheckedItems();
int _type = Types.PATH;
long rowId = addPoi(_type);
dbHandler.addPoiOptions(rowId, options);
}
})
.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
return builder.create();
}
}
public class AddBreakpointDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final List<Integer> mSelectedItems = new ArrayList<>();
final CheckboxImageAdapter adapter = new CheckboxImageAdapter(MainActivity.this, breakPointOptions, null, breakPointOptionsImgs);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.break_point_dialog_title)
.setIcon(res.getDrawable(R.drawable.break_point))
.setPositiveButton(R.string.ok_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int[] options = adapter.getCheckedItems();
int _type = Types.BREAK_POINT;
long rowId = addPoi(_type);
dbHandler.addPoiOptions(rowId, options);
}
})
.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
return builder.create();
}
}
private long addPoi(int _type){
double _lat = mLocation.getLatitude();
double _lon = mLocation.getLongitude();
double _alt = mLocation.getAltitude();
long _time = System.currentTimeMillis() / 1000;
Poi poi = new Poi(_lat, _lon, _alt, _type, _time);
long rowId = dbHandler.addPoi(poi);
if(rowId >= 0) Toaster(getString(R.string.add_poi_success), true);
return rowId;
}
private class ImageListAdapter extends ArrayAdapter<String> {
private final Activity context;
private final String[] texts;
private final Integer[] imgs;
public ImageListAdapter(Activity context, String[] texts, Integer[] imgs) {
super(context, R.layout.drawer_list_item, texts);
this.context = context;
this.texts = texts;
this.imgs = imgs;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.drawer_list_item, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.toggleEntryDesc);
ImageView imageView = (ImageView) rowView.findViewById(R.id.toggleEntryImg);
txtTitle.setText(texts[position]);
imageView.setImageResource(imgs[position]);
return rowView;
}
}
@Override
public void setTitle(CharSequence title){
mTitle = title;
ActionBar actionBar = getSupportActionBar();
if(actionBar != null) actionBar.setTitle(mTitle);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(provider, GPS_MIN_TIME, GPS_MIN_DIST, this);
}
@Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
public void restoreActionBar() {
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(mTitle);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
}
}