/**
* 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.Comparator;
import java.util.List;
import net.naonedbus.NBApplication;
import net.naonedbus.R;
import net.naonedbus.activity.impl.ParkingDetailActivity;
import net.naonedbus.bean.async.AsyncResult;
import net.naonedbus.bean.parking.Parking;
import net.naonedbus.bean.parking.pub.ParkingPublic;
import net.naonedbus.comparator.ParkingComparator;
import net.naonedbus.comparator.ParkingDistanceComparator;
import net.naonedbus.comparator.ParkingPlacesComparator;
import net.naonedbus.fragment.CustomListFragment;
import net.naonedbus.helper.StateHelper;
import net.naonedbus.manager.impl.ParkingPublicManager;
import net.naonedbus.provider.impl.NaoLocationManager;
import net.naonedbus.provider.impl.NaoLocationManager.NaoLocationListener;
import net.naonedbus.widget.adapter.impl.ParkingPublicArrayAdapter;
import net.naonedbus.widget.indexer.ArraySectionIndexer;
import net.naonedbus.widget.indexer.impl.ParkingDistanceIndexer;
import net.naonedbus.widget.indexer.impl.ParkingNomIndexer;
import net.naonedbus.widget.indexer.impl.ParkingPlaceIndexer;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
public class ParkingsPublicsFragment extends CustomListFragment {
private final static int SORT_NOM = 0;
private final static int SORT_DISTANCE = 1;
private final static int SORT_PLACES = 2;
private final static SparseIntArray MENU_MAPPING = new SparseIntArray();
static {
MENU_MAPPING.append(SORT_NOM, R.id.menu_sort_name);
MENU_MAPPING.append(SORT_DISTANCE, R.id.menu_sort_distance);
MENU_MAPPING.append(SORT_PLACES, R.id.menu_sort_parking_places);
}
private final static SparseArray<Comparator<ParkingPublic>> comparators = new SparseArray<Comparator<ParkingPublic>>();
static {
comparators.append(SORT_NOM, new ParkingComparator());
comparators.append(SORT_DISTANCE, new ParkingDistanceComparator());
comparators.append(SORT_PLACES, new ParkingPlacesComparator());
}
private final static SparseArray<ArraySectionIndexer<ParkingPublic>> indexers = new SparseArray<ArraySectionIndexer<ParkingPublic>>();
static {
indexers.append(SORT_NOM, new ParkingNomIndexer());
indexers.append(SORT_DISTANCE, new ParkingDistanceIndexer());
indexers.append(SORT_PLACES, new ParkingPlaceIndexer());
}
private MenuItem mRefreshMenuItem;
private StateHelper mStateHelper;
private final NaoLocationManager myLocationProvider;
private ParkingDistance loaderDistance;
private int mCurrentSort = SORT_NOM;
public ParkingsPublicsFragment() {
super(R.layout.fragment_listview_section);
myLocationProvider = NBApplication.getLocationProvider();
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myLocationProvider.addListener(locationListener);
// Initaliser le comparator avec la position actuelle.
locationListener.onLocationChanged(myLocationProvider.getLastLocation());
mStateHelper = new StateHelper(getActivity());
mCurrentSort = mStateHelper.getSortType(this, SORT_NOM);
setHasOptionsMenu(true);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setDividerHeight(0);
loadContent();
}
@Override
public void onResume() {
super.onResume();
myLocationProvider.removeListener(locationListener);
}
@Override
public void onStop() {
mStateHelper.setSortType(this, mCurrentSort);
super.onStop();
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.fragment_parkings_publics, menu);
mRefreshMenuItem = menu.findItem(R.id.menu_refresh);
menu.findItem(MENU_MAPPING.get(mCurrentSort)).setChecked(true);
if (getLoaderManager().hasRunningLoaders())
showResfrehMenuLoader();
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
item.setChecked(true);
switch (item.getItemId()) {
case R.id.menu_sort_name:
mCurrentSort = SORT_NOM;
sort();
break;
case R.id.menu_sort_distance:
mCurrentSort = SORT_DISTANCE;
sort();
break;
case R.id.menu_sort_parking_places:
mCurrentSort = SORT_PLACES;
sort();
break;
case R.id.menu_refresh:
refreshContent();
break;
}
return false;
}
private void showResfrehMenuLoader() {
if (mRefreshMenuItem != null) {
mRefreshMenuItem.setActionView(R.layout.action_item_refresh);
}
}
private void hideResfrehMenuLoader() {
if (mRefreshMenuItem != null) {
mRefreshMenuItem.setActionView(null);
}
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
super.onListItemClick(l, v, position, id);
final Parking parking = (Parking) getListAdapter().getItem(position);
final Intent intent = new Intent(getActivity(), ParkingDetailActivity.class);
intent.putExtra(ParkingDetailActivity.PARAM_PARKING, parking);
startActivity(intent);
}
private void refreshDistance() {
if (myLocationProvider.isEnabled() && getListAdapter() != null
&& (loaderDistance == null || loaderDistance.getStatus() == AsyncTask.Status.FINISHED)) {
loaderDistance = (ParkingDistance) new ParkingDistance().execute();
}
}
@Override
protected void onPreExecute() {
if (getListAdapter() == null) {
showLoader();
}
showResfrehMenuLoader();
}
@Override
protected AsyncResult<ListAdapter> loadContent(final Context context, final Bundle bundle) {
final AsyncResult<ListAdapter> result = new AsyncResult<ListAdapter>();
try {
final ParkingPublicManager parkingPublicManager = ParkingPublicManager.getInstance();
final List<ParkingPublic> parkings = parkingPublicManager.getAll(context);
Collections.sort(parkings, comparators.get(mCurrentSort));
final ParkingPublicArrayAdapter adapter = new ParkingPublicArrayAdapter(context, parkings);
adapter.setIndexer(indexers.get(mCurrentSort));
result.setResult(adapter);
} catch (final Exception exception) {
result.setException(exception);
}
return result;
}
@Override
protected void onPostExecute() {
refreshDistance();
hideResfrehMenuLoader();
}
/**
* Classe de calcul de la distance des parkings.
*
* @author romain
*/
private class ParkingDistance extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(final Void... params) {
final ListAdapter adapter = getListAdapter();
final Location parkingLocation = new Location(LocationManager.GPS_PROVIDER);
final Location currentLocation = myLocationProvider.getLastLocation();
if (currentLocation != null) {
for (int i = 0; i < adapter.getCount(); i++) {
final ParkingPublic item = (ParkingPublic) adapter.getItem(i);
if (item.getLatitude() != null) {
parkingLocation.setLatitude(item.getLatitude());
parkingLocation.setLongitude(item.getLongitude());
item.setDistance(currentLocation.distanceTo(parkingLocation));
} else {
item.setDistance(null);
}
}
}
return null;
}
@Override
protected void onPostExecute(final Void result) {
sort();
}
}
/**
* Trier les parkings selon les préférences.
*/
private void sort() {
final ParkingPublicArrayAdapter adapter = (ParkingPublicArrayAdapter) getListAdapter();
if (adapter != null) {
sort(adapter);
adapter.notifyDataSetChanged();
}
}
/**
* Trier les parkings selon les préférences.
*
* @param adapter
*/
private void sort(final ParkingPublicArrayAdapter adapter) {
final Comparator<ParkingPublic> comparator;
final ArraySectionIndexer<ParkingPublic> indexer;
if (mCurrentSort == SORT_DISTANCE && !myLocationProvider.isEnabled()) {
// Tri par défaut si pas le localisation
comparator = comparators.get(SORT_NOM);
indexer = indexers.get(SORT_NOM);
} else {
comparator = comparators.get(mCurrentSort);
indexer = indexers.get(mCurrentSort);
}
adapter.sort(comparator);
adapter.setIndexer(indexer);
}
/**
* Listener de changement de coordonnées GPS
*/
private final NaoLocationListener locationListener = new NaoLocationListener() {
@Override
public void onLocationChanged(final Location location) {
final ParkingDistanceComparator comparator = (ParkingDistanceComparator) comparators.get(SORT_DISTANCE);
comparator.setReferentiel(location);
if (mCurrentSort == SORT_DISTANCE) {
refreshDistance();
}
}
@Override
public void onDisconnected() {
final ParkingDistanceComparator comparator = (ParkingDistanceComparator) comparators.get(SORT_DISTANCE);
comparator.setReferentiel(null);
if (mCurrentSort == SORT_DISTANCE) {
mCurrentSort = SORT_NOM;
sort();
}
}
@Override
public void onConnecting() {
}
@Override
public void onLocationTimeout() {
}
};
}