/**
* Copyright (C) 2013 Romain Guefveneu.
*
* This file is part of naonedbus.
*
* Naonedbus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Naonedbus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.naonedbus.fragment.impl;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.naonedbus.BuildConfig;
import net.naonedbus.NBApplication;
import net.naonedbus.R;
import net.naonedbus.activity.impl.CommentaireActivity;
import net.naonedbus.activity.impl.MapActivity;
import net.naonedbus.activity.impl.ParcoursActivity;
import net.naonedbus.bean.Equipement;
import net.naonedbus.bean.Equipement.Type;
import net.naonedbus.bean.async.AsyncResult;
import net.naonedbus.comparator.EquipementDistanceComparator;
import net.naonedbus.fragment.CustomListFragment;
import net.naonedbus.manager.impl.EquipementManager;
import net.naonedbus.provider.impl.NaoLocationManager;
import net.naonedbus.provider.impl.NaoLocationManager.NaoLocationListener;
import net.naonedbus.task.AddressResolverTask;
import net.naonedbus.task.AddressResolverTask.AddressTaskListener;
import net.naonedbus.utils.FormatUtils;
import net.naonedbus.widget.adapter.impl.EquipementArrayAdapter;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.SubMenu;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
public class ProximiteFragment extends CustomListFragment implements NaoLocationListener, AddressTaskListener {
private static final String LOG_TAG = "ProximiteFragment";
private static final boolean DBG = BuildConfig.DEBUG;
private static final int MAX_EQUIPEMENTS = 25;
private static final int MENU_GROUP_TYPES = 1;
private static final String PREF_PROXIMITE_LAYER = "proximite.layer.";
private final SharedPreferences mPreferences;
private final NaoLocationManager mLocationProvider;
private final Set<Equipement.Type> mSelectedTypesEquipements;
private AddressResolverTask mAddressResolverTask;
private Location mLastLoadedLocation;
private String mLastAddress;
private boolean mPlayServiceSuccess;
private TextView mHeaderTextView;
public ProximiteFragment() {
super(R.layout.fragment_proximite);
if (DBG)
Log.i(LOG_TAG, "ProximiteFragment()");
setHasOptionsMenu(true);
mLocationProvider = NBApplication.getLocationProvider();
mPreferences = NBApplication.getPreferences();
mSelectedTypesEquipements = new HashSet<Equipement.Type>();
final Equipement.Type[] types = Equipement.Type.values();
for (final Equipement.Type type : types) {
if (isLayerPreferenceEnabled(type.getId())) {
mSelectedTypesEquipements.add(type);
}
}
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onResume() {
super.onResume();
if (mPlayServiceSuccess == false) {
tryToLoad();
}
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
if (DBG)
Log.d(LOG_TAG, "onCreateView");
final View view = super.onCreateView(inflater, container, savedInstanceState);
mHeaderTextView = (TextView) view.findViewById(R.id.text);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mLocationProvider.addListener(this);
}
private void tryToLoad() {
mPlayServiceSuccess = checkPlayServices();
if (mPlayServiceSuccess) {
showContent();
} else {
int errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
final String title = getString(R.string.msg_error_location_title);
final String summary = GooglePlayServicesUtil.d(getActivity(), errorCode);
final String buttonTitle = GooglePlayServicesUtil.e(getActivity(), errorCode);
final PendingIntent intent = GooglePlayServicesUtil.getErrorPendingIntent(errorCode, getActivity(), 0);
showMessage(title, summary, R.drawable.ic_extension);
setMessageButton(buttonTitle, new OnClickListener() {
@Override
public void onClick(final View v) {
try {
intent.send();
} catch (final CanceledException e) {
e.printStackTrace();
}
}
});
}
}
@Override
public void onDestroy() {
super.onDestroy();
mLocationProvider.removeListener(this);
}
@Override
public void onStop() {
super.onStop();
if (DBG)
Log.d(LOG_TAG, "onStop");
if (mAddressResolverTask != null) {
mAddressResolverTask.cancel(false);
}
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.fragment_proximite, menu);
final SubMenu filterSubMenu = menu.findItem(R.id.menu_filter).getSubMenu();
final Equipement.Type[] types = Equipement.Type.values();
for (final Equipement.Type type : types) {
final MenuItem item = filterSubMenu.add(MENU_GROUP_TYPES, type.getId(), 0, type.getTitleRes());
item.setCheckable(true);
item.setChecked((mSelectedTypesEquipements.contains(type)));
}
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(final Menu menu) {
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
if (item.getGroupId() == MENU_GROUP_TYPES) {
final Equipement.Type type = Equipement.Type.getTypeById(item.getItemId());
item.setChecked(!item.isChecked());
setLayerPreference(type.getId(), item.isChecked());
if (item.isChecked()) {
mSelectedTypesEquipements.add(type);
} else {
mSelectedTypesEquipements.remove(type);
}
refreshContent();
return true;
} else {
switch (item.getItemId()) {
case R.id.menu_edit:
startActivity(new Intent(getActivity(), CommentaireActivity.class));
break;
default:
return false;
}
}
return false;
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
final Equipement equipement = (Equipement) getListAdapter().getItem(position);
final Intent intent;
if (equipement.getType().equals(Type.TYPE_ARRET)) {
intent = new Intent(getActivity(), ParcoursActivity.class);
intent.putExtra(ParcoursActivity.PARAM_ID_SATION, equipement.getId());
} else {
intent = new Intent(getActivity(), MapActivity.class);
intent.putExtra(MapFragment.PARAM_ITEM_ID, equipement.getId());
intent.putExtra(MapFragment.PARAM_ITEM_TYPE, equipement.getType().getId());
}
startActivity(intent);
}
/**
* Lance la récupération de l'adresse courante.
*
* @param location
*/
private void loadAddress() {
if (mAddressResolverTask != null) {
mAddressResolverTask.cancel(true);
}
mAddressResolverTask = (AddressResolverTask) new AddressResolverTask(this).execute();
}
@Override
protected AsyncResult<ListAdapter> loadContent(final Context context, final Bundle bundle) {
final AsyncResult<ListAdapter> result = new AsyncResult<ListAdapter>();
EquipementArrayAdapter adapter = null;
try {
if (mSelectedTypesEquipements.size() > 0) {
final EquipementManager equipementManager = EquipementManager.getInstance();
final Location location = mLocationProvider.getLastLocation();
if (location != null) {
mLastLoadedLocation = location;
final List<Equipement> list = equipementManager.getEquipementsByLocation(
context.getContentResolver(), mSelectedTypesEquipements, location, MAX_EQUIPEMENTS);
setDistances(list);
Collections.sort(list, new EquipementDistanceComparator<Equipement>());
adapter = new EquipementArrayAdapter(context, list);
}
}
result.setResult(adapter);
} catch (final Exception e) {
result.setException(e);
}
return result;
}
protected void setDistances(final List<Equipement> equipements) {
final Location location = new Location(LocationManager.GPS_PROVIDER);
final Location currentLocation = mLocationProvider.getLastLocation();
if (currentLocation != null) {
for (final Equipement item : equipements) {
final double latitude = item.getLatitude();
final double longitude = item.getLongitude();
if (latitude != 0) {
location.setLatitude(latitude);
location.setLongitude(longitude);
item.setDistance(currentLocation.distanceTo(location));
}
}
}
}
@Override
public void onConnecting() {
mHeaderTextView.setVisibility(View.VISIBLE);
mHeaderTextView.setText(R.string.msg_loading_address);
showLoader();
}
@Override
public void onLocationChanged(final Location location) {
if (DBG)
Log.d(LOG_TAG, "onLocationChanged " + location);
if (mLastLoadedLocation == null || mLastLoadedLocation.distanceTo(location) > 10f) {
refreshContent();
showContent();
loadAddress();
}
}
@Override
public void onDisconnected() {
if (DBG)
Log.d(LOG_TAG, "onLocationDisabled");
mHeaderTextView.setVisibility(View.GONE);
if (mPlayServiceSuccess == true) {
showMessage(R.string.msg_error_location_title, R.string.msg_error_location_desc, R.drawable.ic_location_disabled);
setMessageButton(R.string.btn_geolocation_service, new OnClickListener() {
@Override
public void onClick(final View v) {
final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
getActivity().startActivity(intent);
}
});
}
}
@Override
public void onLocationTimeout() {
mHeaderTextView.setVisibility(View.GONE);
if (mPlayServiceSuccess == true) {
showMessage(R.string.error_title_empty, R.string.error_summary_empty, R.drawable.ic_location_disabled);
setMessageButton(R.string.btn_geolocation_service, new OnClickListener() {
@Override
public void onClick(final View v) {
final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
getActivity().startActivity(intent);
}
});
}
}
/**
* Indique si le calque est activé ou non dans les préférences. Le calque
* {@code TYPE_STATION} est actif par défaut.
*
* @param id
* @return Vrai si le calque est activé.
*/
private boolean isLayerPreferenceEnabled(final int id) {
if (id == Equipement.Type.TYPE_ARRET.getId()) {
return mPreferences.getBoolean(PREF_PROXIMITE_LAYER + id, true);
} else {
return mPreferences.getBoolean(PREF_PROXIMITE_LAYER + id, false);
}
}
/**
* Changer la valeur d'activation d'un calque.
*
* @param id
* @param enabled
*/
private void setLayerPreference(final Integer id, final boolean enabled) {
mPreferences.edit().putBoolean(PREF_PROXIMITE_LAYER + id, enabled).commit();
}
@Override
public void onAddressTaskPreExecute() {
mHeaderTextView.setText(R.string.msg_loading_address);
}
@Override
public void onAddressTaskResult(final Address address) {
if (address != null) {
mLastAddress = FormatUtils.formatAddress(address, null);
mHeaderTextView.setText(mLastAddress);
} else {
mHeaderTextView.setText(R.string.error_current_address);
}
}
private boolean checkPlayServices() {
final int checkGooglePlayServices = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
return checkGooglePlayServices == ConnectionResult.SUCCESS;
}
}