package mil.nga.giat.asam.map;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.List;
import mil.nga.giat.asam.Asam;
import mil.nga.giat.asam.AsamListActivity;
import mil.nga.giat.asam.AsamReportActivity;
import mil.nga.giat.asam.R;
import mil.nga.giat.asam.connectivity.OfflineBannerFragment;
import mil.nga.giat.asam.db.AsamDbHelper;
import mil.nga.giat.asam.model.AsamBean;
import mil.nga.giat.asam.model.AsamJsonParser;
import mil.nga.giat.asam.model.AsamMapClusterBean;
import mil.nga.giat.asam.model.TextQueryParametersBean;
import mil.nga.giat.asam.net.AsamWebService;
import mil.nga.giat.asam.util.AsamConstants;
import mil.nga.giat.asam.util.AsamListContainer;
import mil.nga.giat.asam.util.AsamLog;
import mil.nga.giat.asam.util.AsamUtils;
import mil.nga.giat.asam.util.SyncTime;
import mil.nga.giat.poffencluster.PoffenCluster;
import mil.nga.giat.poffencluster.PoffenClusterCalculator;
import mil.nga.giat.poffencluster.PoffenPoint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.CancelableCallback;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.vividsolutions.jts.geom.Geometry;
public class AllAsamsMapActivity extends ActionBarActivity implements OnCameraChangeListener, OnMarkerClickListener, CancelableCallback, Asam.OnOfflineFeaturesListener, OfflineBannerFragment.OnOfflineBannerClick {
private static class QueryHandler extends Handler {
WeakReference<AllAsamsMapActivity> mAllAsamsMapActivity;
QueryHandler(AllAsamsMapActivity allAsamsMapActivity) {
mAllAsamsMapActivity = new WeakReference<AllAsamsMapActivity>(allAsamsMapActivity);
}
@Override
public void handleMessage(Message message) {
AllAsamsMapActivity allAsamsMapActivity = mAllAsamsMapActivity.get();
allAsamsMapActivity.mQueryProgressDialog.dismiss();
if (allAsamsMapActivity.mQueryError) {
allAsamsMapActivity.mQueryError = false;
Toast.makeText(allAsamsMapActivity, allAsamsMapActivity.getString(R.string.all_asams_map_query_error_text), Toast.LENGTH_LONG).show();
}
allAsamsMapActivity.clearAsamMarkers();
if (allAsamsMapActivity.mAsams.size() == 1) {
allAsamsMapActivity.mPerformMapClustering = true;
AsamBean asam = allAsamsMapActivity.mAsams.get(0);
allAsamsMapActivity.mMapUI.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().target(new LatLng(asam.getLatitude(), asam.getLongitude())).zoom(AsamConstants.SINGLE_ASAM_ZOOM_LEVEL).build()));
}
else if (allAsamsMapActivity.mAsams.size() > 1) {
allAsamsMapActivity.mPerformMapClustering = true;
LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
for (AsamBean asam : allAsamsMapActivity.mAsams) {
boundsBuilder = boundsBuilder.include(new LatLng(asam.getLatitude(), asam.getLongitude()));
}
allAsamsMapActivity.mMapUI.moveCamera(CameraUpdateFactory.scrollBy(0.5f, 0.0f)); // Needed in case camera doesn't move the view.
allAsamsMapActivity.mMapUI.animateCamera(CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 0), allAsamsMapActivity);
}
else {
Toast.makeText(allAsamsMapActivity, allAsamsMapActivity.getString(R.string.all_asams_map_no_asams_text), Toast.LENGTH_LONG).show();
}
// Now set the feedback title.
StringBuilder feedbackText = new StringBuilder("");
if (allAsamsMapActivity.mQueryType == AsamConstants.ALL_ASAMS_QUERY) {
if (allAsamsMapActivity.mAsams.size() == 1) {
feedbackText.append(String.format(allAsamsMapActivity.getString(R.string.all_asams_map_1_asam_text_with_timespan), allAsamsMapActivity.mTimeSpanTitleText));
}
else {
feedbackText.append(String.format(allAsamsMapActivity.getString(R.string.all_asams_map_multiple_asams_text_with_timespan), allAsamsMapActivity.mAsams.size(), allAsamsMapActivity.mTimeSpanTitleText));
}
}
else if (allAsamsMapActivity.mQueryType == AsamConstants.SUBREGION_QUERY) {
if (allAsamsMapActivity.mAsams.size() == 1) {
feedbackText.append(String.format(allAsamsMapActivity.getString(R.string.all_asams_map_1_asam_text_with_timespan_with_subregions), allAsamsMapActivity.mTimeSpanTitleText, allAsamsMapActivity.mSubregionsTitleText));
}
else {
feedbackText.append(String.format(allAsamsMapActivity.getString(R.string.all_asams_map_multiple_asams_text_with_timespan_with_subregions), allAsamsMapActivity.mAsams.size(), allAsamsMapActivity.mTimeSpanTitleText, allAsamsMapActivity.mSubregionsTitleText));
}
}
else if (allAsamsMapActivity.mQueryType == AsamConstants.TEXT_QUERY) {
if (allAsamsMapActivity.mAsams.size() == 1) {
feedbackText.append(allAsamsMapActivity.getString(R.string.all_asams_map_1_asam_text));
}
else {
feedbackText.append(String.format(allAsamsMapActivity.getString(R.string.all_asams_map_multiple_asams_text), allAsamsMapActivity.mAsams.size()));
}
}
allAsamsMapActivity.mQueryFeedbackUI.setText(feedbackText.toString());
}
}
private final Object Mutex = new Object();
private volatile boolean mQueryError;
private volatile boolean mPerformMapClustering;
private List<AsamBean> mAsams;
private List<AsamMapClusterBean> mMapClusters;
private TextView mQueryFeedbackUI;
private GoogleMap mMapUI;
private int mMapType;
private ProgressDialog mQueryProgressDialog;
private QueryHandler mQueryHandler;
private String mTimeSpanTitleText;
private String mSubregionsTitleText;
private int mQueryType;
private int mPreviousZoomLevel;
private List<AsamMapClusterBean> mVisibleClusters;
private SharedPreferences mSharedPreferences;
private Collection<Geometry> offlineGeometries = null;
private OfflineMap offlineMap;
private MenuItem offlineMap110mMenuItem;
private OfflineBannerFragment offlineAlertFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AsamLog.i(AllAsamsMapActivity.class.getName() + ":onCreate");
setContentView(R.layout.all_asams_map);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
mQueryError = false;
mPerformMapClustering = false;
mAsams = new ArrayList<AsamBean>();
mMapClusters = new ArrayList<AsamMapClusterBean>();
mVisibleClusters = new ArrayList<AsamMapClusterBean>();
mQueryFeedbackUI = (TextView)findViewById(R.id.all_asams_map_query_feedback_text_ui);
mMapUI = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.all_asams_map_map_view_ui)).getMap();
mMapUI.setOnCameraChangeListener(this);
mMapUI.setOnMarkerClickListener(this);
mPreviousZoomLevel = -1;
offlineAlertFragment = new OfflineBannerFragment();
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, offlineAlertFragment)
.commit();
// Called to handle the UI after the query has run.
mQueryHandler = new QueryHandler(this);
mQueryProgressDialog = ProgressDialog.show(this, getString(R.string.all_asams_map_query_progress_dialog_title_text), getString(R.string.all_asams_map_query_progress_dialog_content_text), true);
Intent intent = getIntent();
mQueryType = intent.getIntExtra(AsamConstants.QUERY_TYPE_KEY, AsamConstants.ALL_ASAMS_QUERY);
switch (mQueryType) {
case AsamConstants.SUBREGION_QUERY:
int queryTimeSpan = intent.getIntExtra(AsamConstants.SUBREGION_QUERY_TIME_SPAN_KEY, -1);
List<Integer> selectedSubregionIds = intent.getIntegerArrayListExtra(AsamConstants.SUBREGION_QUERY_SUBREGIONS_LIST_KEY);
if (selectedSubregionIds.size() == 1) {
mSubregionsTitleText = getString(R.string.all_asams_map_1_subregion_text);
}
else {
mSubregionsTitleText = String.format(getString(R.string.all_asams_map_multiple_subregions_text), selectedSubregionIds.size());
}
if (queryTimeSpan == AsamConstants.TIME_SPAN_60_DAYS) {
mTimeSpanTitleText = getString(R.string.query_60_days_text);
}
else if (queryTimeSpan == AsamConstants.TIME_SPAN_90_DAYS) {
mTimeSpanTitleText = getString(R.string.query_90_days_text);
}
else if (queryTimeSpan == AsamConstants.TIME_SPAN_180_DAYS) {
mTimeSpanTitleText = getString(R.string.query_180_days_text);
}
else if (queryTimeSpan == AsamConstants.TIME_SPAN_1_YEAR) {
mTimeSpanTitleText = getString(R.string.query_1_year_text);
}
else if (queryTimeSpan == AsamConstants.TIME_SPAN_5_YEARS) {
mTimeSpanTitleText = getString(R.string.query_5_years_text);
}
else if (queryTimeSpan == AsamConstants.TIME_SPAN_ALL) {
mTimeSpanTitleText = getString(R.string.query_all_text);
}
new QueryThread(queryTimeSpan, selectedSubregionIds).start();
break;
case AsamConstants.ALL_ASAMS_QUERY:
mTimeSpanTitleText = getString(R.string.query_1_year_text); // Start off with this.
new QueryThread(AsamConstants.TIME_SPAN_1_YEAR).start();
break;
case AsamConstants.TEXT_QUERY:
TextQueryParametersBean parameters = (TextQueryParametersBean)intent.getSerializableExtra(AsamConstants.TEXT_QUERY_PARAMETERS_KEY);
new QueryThread(parameters).start();
break;
}
}
@Override
public void onResume() {
super.onResume();
((Asam) getApplication()).registerOfflineMapListener(this);
supportInvalidateOptionsMenu();
int mapType = mSharedPreferences.getInt(AsamConstants.MAP_TYPE_KEY, GoogleMap.MAP_TYPE_NORMAL);
if (mapType != mMapType) onMapTypeChanged(mapType);
}
@Override
public void onPause() {
super.onPause();
((Asam) getApplication()).unregisterOfflineMapListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.all_asams_map_menu, menu);
if (mQueryType == AsamConstants.SUBREGION_QUERY || mQueryType == AsamConstants.TEXT_QUERY) {
MenuItem queryUI = menu.findItem(R.id.all_asams_map_menu_query_ui);
queryUI.setVisible(false);
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
int mapType = mSharedPreferences.getInt(AsamConstants.MAP_TYPE_KEY, 1);
switch (mapType) {
case GoogleMap.MAP_TYPE_SATELLITE:
menu.findItem(R.id.map_type_satellite).setChecked(true);
break;
case GoogleMap.MAP_TYPE_HYBRID:
menu.findItem(R.id.map_type_hybrid).setChecked(true);
break;
case AsamConstants.MAP_TYPE_OFFLINE_110M:
menu.findItem(R.id.map_type_offline_110m).setChecked(true);
break;
default:
menu.findItem(R.id.map_type_normal).setChecked(true);
}
offlineMap110mMenuItem = menu.findItem(R.id.map_type_offline_110m);
if (offlineGeometries != null) offlineMap110mMenuItem.setVisible(true);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: {
finish();
return true;
}
case R.id.map_type_normal:
item.setChecked(!item.isChecked());
onMapTypeChanged(GoogleMap.MAP_TYPE_NORMAL);
return true;
case R.id.map_type_satellite:
item.setChecked(!item.isChecked());
onMapTypeChanged(GoogleMap.MAP_TYPE_SATELLITE);
return true;
case R.id.map_type_hybrid:
item.setChecked(!item.isChecked());
onMapTypeChanged(GoogleMap.MAP_TYPE_HYBRID);
return true;
case R.id.map_type_offline_110m:
item.setChecked(!item.isChecked());
onMapTypeChanged(AsamConstants.MAP_TYPE_OFFLINE_110M);
return true;
case R.id.all_asams_map_menu_zoom_ui:
zoomToOriginalExtent();
return true;
case R.id.all_asams_map_menu_list_view_ui:
AsamListContainer.mAsams = mAsams;
Intent intent = new Intent(this, AsamListActivity.class);
startActivity(intent);
return true;
case R.id.all_asams_map_menu_60_days_ui:
runQuery(getString(R.string.query_60_days_text), AsamConstants.TIME_SPAN_60_DAYS);
return true;
case R.id.all_asams_map_menu_90_days_ui:
runQuery(getString(R.string.query_90_days_text), AsamConstants.TIME_SPAN_90_DAYS);
return true;
case R.id.all_asams_map_menu_180_days_ui:
runQuery(getString(R.string.query_180_days_text), AsamConstants.TIME_SPAN_180_DAYS);
return true;
case R.id.all_asams_map_menu_1_year_ui:
runQuery(getString(R.string.query_1_year_text), AsamConstants.TIME_SPAN_1_YEAR);
return true;
case R.id.all_asams_map_menu_5_years_ui:
runQuery(getString(R.string.query_5_years_text), AsamConstants.TIME_SPAN_5_YEARS);
return true;
case R.id.all_asams_map_menu_all_ui:
runQuery(getString(R.string.query_all_text), AsamConstants.TIME_SPAN_ALL);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onMarkerClick(Marker marker) {
synchronized (Mutex) {
for (AsamMapClusterBean mapCluster : mVisibleClusters) {
if (marker.equals(mapCluster.getMapMarker())) {
Intent intent = null;
if (mapCluster.getNumPointsInCluster() == 1) {
intent = new Intent(this, AsamReportActivity.class);
intent.putExtra(AsamConstants.ASAM_KEY, mapCluster.getAsams().get(0));
}
else {
intent = new Intent(this, AsamListActivity.class);
AsamListContainer.mAsams = mapCluster.getAsams();
}
startActivity(intent);
break;
}
}
}
return true;
}
@Override
public void onCameraChange(CameraPosition position) {
if (mPerformMapClustering) {
mPerformMapClustering = false;
mPreviousZoomLevel = Math.round(mMapUI.getCameraPosition().zoom);
// Use the PoffenCluster library to calculate the clusters.
int zoomLevel = mPreviousZoomLevel;
int numLatitudeCells = (int)(Math.round(Math.pow(2, zoomLevel)));
int numLongitudeCells = (int)(Math.round(Math.pow(2, zoomLevel)));
PoffenClusterCalculator<AsamBean> calculator = new PoffenClusterCalculator.Builder<AsamBean>(numLatitudeCells, numLongitudeCells).mergeLargeClusters(false).build();
for (AsamBean asam : mAsams) {
calculator.add(asam, new PoffenPoint(asam.getLatitude(), asam.getLongitude()));
}
mMapClusters = Collections.synchronizedList(new ArrayList<AsamMapClusterBean>());
mVisibleClusters = new ArrayList<AsamMapClusterBean>();
List<PoffenCluster<AsamBean>> poffenClusters = calculator.getPoffenClusters();
for (PoffenCluster<AsamBean> poffenCluster : poffenClusters) {
PoffenPoint poffenPoint = poffenCluster.getClusterCoordinateClosestToMean();
AsamMapClusterBean cluster = new AsamMapClusterBean(poffenCluster.getClusterItems(), new LatLng(poffenPoint.getLatitude(), poffenPoint.getLongitude()));
mMapClusters.add(cluster);
mVisibleClusters.add(cluster);
// Now draw it on the map.
Marker marker;
if (poffenCluster.getClusterItems().size() == 1) {
marker = mMapUI.addMarker(new MarkerOptions().position(cluster.getClusteredMapPosition()).icon(AsamConstants.PIRATE_MARKER).anchor(0.5f, 0.5f));
}
else {
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(AsamUtils.drawNumberOnClusterMarker(this, poffenCluster.getClusterItems().size()));
marker = mMapUI.addMarker(new MarkerOptions().position(cluster.getClusteredMapPosition()).icon(bitmapDescriptor).anchor(0.5f, 0.5f));
}
cluster.setMapMarker(marker);
}
}
else {
if (mPreviousZoomLevel == -1) {
mPreviousZoomLevel = Math.round(position.zoom);
}
else if (mPreviousZoomLevel != Math.round(position.zoom)) {
mPreviousZoomLevel = Math.round(position.zoom);
new RecalculateAndRedrawClustersBasedOnZoomLevelAsyncTask().execute(Math.round(mMapUI.getCameraPosition().zoom));
}
else {
redrawMarkersOnMapBasedOnVisibleRegion();
}
}
}
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
Thread redrawThread = new Thread() {
@Override
public void run() {
try {
Thread.sleep(250);
}
catch (Exception ignore) {}
runOnUiThread(new Thread() {
@Override
public void run() {
redrawMarkersOnMapBasedOnVisibleRegion();
}
});
}
};
redrawThread.start();
}
@Override
public void onCancel() {
}
@Override
public void onFinish() {
}
private void redrawMarkersOnMapBasedOnVisibleRegion() {
LatLngBounds bounds = mMapUI.getProjection().getVisibleRegion().latLngBounds;
int zoomLevel = Math.round(mMapUI.getCameraPosition().zoom);
final List<AsamMapClusterBean> clustersToAddToMap = new ArrayList<AsamMapClusterBean>();
final List<AsamMapClusterBean> clustersToRemoveFromMap = new ArrayList<AsamMapClusterBean>();
for (AsamMapClusterBean mapCluster : mMapClusters) {
if (bounds.contains(mapCluster.getClusteredMapPosition()) || zoomLevel <= AsamConstants.ZOOM_LEVEL_TO_DRAW_ALL_CLUSTERS) {
clustersToAddToMap.add(mapCluster);
}
}
synchronized (Mutex) {
for (AsamMapClusterBean mapCluster : mVisibleClusters) {
if (!bounds.contains(mapCluster.getClusteredMapPosition()) && zoomLevel > AsamConstants.ZOOM_LEVEL_TO_DRAW_ALL_CLUSTERS) {
clustersToRemoveFromMap.add(mapCluster);
}
}
for (AsamMapClusterBean mapCluster : clustersToRemoveFromMap) {
mapCluster.getMapMarker().remove(); // Remove from map.
mVisibleClusters.remove(mapCluster); // Remove from visible marker list.
}
for (AsamMapClusterBean mapCluster : clustersToAddToMap) {
// Only add it if not already visible.
if (!mVisibleClusters.contains(mapCluster)) {
Marker marker;
if (mapCluster.getAsams().size() == 1) {
marker = mMapUI.addMarker(new MarkerOptions().position(mapCluster.getClusteredMapPosition()).icon(AsamConstants.PIRATE_MARKER).anchor(0.5f, 0.5f));
}
else {
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(AsamUtils.drawNumberOnClusterMarker(AllAsamsMapActivity.this, mapCluster.getAsams().size()));
marker = mMapUI.addMarker(new MarkerOptions().position(mapCluster.getClusteredMapPosition()).icon(bitmapDescriptor).anchor(0.5f, 0.5f));
}
mapCluster.setMapMarker(marker);
mVisibleClusters.add(mapCluster);
}
}
}
}
private void runQuery(String timeSpanText, int timeSpan) {
mTimeSpanTitleText = timeSpanText;
mQueryProgressDialog = ProgressDialog.show(this, getString(R.string.all_asams_map_query_progress_dialog_title_text), getString(R.string.all_asams_map_query_progress_dialog_content_text), true);
new QueryThread(timeSpan).start();
}
private void zoomToOriginalExtent() {
synchronized (Mutex) {
if (mMapClusters.size() > 0) {
LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
for (AsamMapClusterBean mapCluster : mMapClusters) {
boundsBuilder = boundsBuilder.include(mapCluster.getClusteredMapPosition());
}
mMapUI.animateCamera(CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 0));
}
}
}
private class RecalculateAndRedrawClustersBasedOnZoomLevelAsyncTask extends AsyncTask<Integer, Void, Void> {
@Override
protected void onPreExecute() {
clearAsamMarkers();
}
@Override
protected Void doInBackground(Integer... zoomLevel) {
mMapClusters.clear();
if (mAsams.size() < AsamConstants.MAX_NUM_ASAMS_FOR_NO_CLUSTERING_WITH_ZOOM_LEVEL && zoomLevel[0] > AsamConstants.MAX_ZOOM_LEVEL_FOR_CLUSTERING) {
// Turn off clustering. Zoomed in enough.
for (AsamBean asam : mAsams) {
List<AsamBean> asams = new ArrayList<AsamBean>();
asams.add(asam);
AsamMapClusterBean cluster = new AsamMapClusterBean(asams, new LatLng(asam.getLatitude(), asam.getLongitude()));
mMapClusters.add(cluster);
}
}
else {
// Use the PoffenCluster library to calculate the clusters.
int numLatitudeCells = (int)(Math.round(Math.pow(2, zoomLevel[0])));
int numLongitudeCells = (int)(Math.round(Math.pow(2, zoomLevel[0])));
PoffenClusterCalculator<AsamBean> calculator = new PoffenClusterCalculator.Builder<AsamBean>(numLatitudeCells, numLongitudeCells).mergeLargeClusters(false).build();
for (AsamBean asam : mAsams) {
calculator.add(asam, new PoffenPoint(asam.getLatitude(), asam.getLongitude()));
}
List<PoffenCluster<AsamBean>> poffenClusters = calculator.getPoffenClusters();
for (PoffenCluster<AsamBean> poffenCluster : poffenClusters) {
PoffenPoint poffenPoint = poffenCluster.getClusterCoordinateClosestToMean();
AsamMapClusterBean cluster = new AsamMapClusterBean(poffenCluster.getClusterItems(), new LatLng(poffenPoint.getLatitude(), poffenPoint.getLongitude()));
mMapClusters.add(cluster);
}
}
synchronized (Mutex) {
mVisibleClusters.clear();
}
return null;
}
@Override
protected void onPostExecute(Void empty) {
redrawMarkersOnMapBasedOnVisibleRegion();
}
}
private class QueryThread extends Thread {
private int mTimeSpan;
List<Integer> mSelectedSubregions;
TextQueryParametersBean mTextQueryParameters;
QueryThread(int timeSpan) {
mTimeSpan = timeSpan;
}
QueryThread(int timeSpan, List<Integer> selectedSubregions) {
mTimeSpan = timeSpan;
mSelectedSubregions = selectedSubregions;
}
QueryThread(TextQueryParametersBean textQueryParameters) {
mTextQueryParameters = textQueryParameters;
}
@Override
public void run() {
Context context = AllAsamsMapActivity.this;
String json = null;
SQLiteDatabase db = null;
if (!SyncTime.isSynched(context)) {
try {
AsamWebService webService = new AsamWebService(context);
json = webService.query();
if (!AsamUtils.isEmpty(json)) {
AsamJsonParser parser = new AsamJsonParser();
List<AsamBean> asams = parser.parseJson(json);
if (asams.size() > 0) {
// Do a diff of what the web service returned and what's currently in the db.
AsamDbHelper dbHelper = new AsamDbHelper(context);
db = dbHelper.getWritableDatabase();
asams = dbHelper.removeDuplicates(db, asams);
dbHelper.insertAsams(db, asams);
}
}
SyncTime.finishedSync(context);
}
catch (Exception caught) {
AsamLog.e(AllAsamsMapActivity.class.getName() + ":There was an error parsing ASAM feed", caught);
mQueryError = true;
}
finally {
if (db != null) {
db.close();
db = null;
}
}
}
try {
// Query for the time period.
Calendar timePeriod = new GregorianCalendar();
if (mTimeSpan == AsamConstants.TIME_SPAN_1_YEAR) {
timePeriod.add(Calendar.YEAR, -1);
}
else if (mTimeSpan == AsamConstants.TIME_SPAN_5_YEARS) {
timePeriod.add(Calendar.YEAR, -5);
}
else {
timePeriod.add(Calendar.DAY_OF_YEAR, -mTimeSpan);
}
synchronized (Mutex) {
mAsams.clear();
AsamDbHelper dbHelper = new AsamDbHelper(context);
db = dbHelper.getReadableDatabase();
if (mSelectedSubregions != null) {
mAsams.addAll(dbHelper.queryByTimeAndSubregions(db, timePeriod, mSelectedSubregions));
}
else if (mTextQueryParameters != null) {
mAsams.addAll(dbHelper.queryByText(db, mTextQueryParameters));
}
else {
mAsams.addAll(dbHelper.queryByTime(db, timePeriod));
}
}
}
finally {
if (db != null) {
db.close();
}
}
mQueryHandler.sendEmptyMessage(0);
}
}
private void clearAsamMarkers() {
for (AsamMapClusterBean mapCluster : mVisibleClusters) {
mapCluster.getMapMarker().remove(); // Remove from map.
}
}
public void onMapTypeChanged(int mapType) {
mMapType = mapType;
// Show/hide the offline alert fragment based on map type
if (mMapType == AsamConstants.MAP_TYPE_OFFLINE_110M) {
getSupportFragmentManager()
.beginTransaction()
.hide(offlineAlertFragment)
.commit();
} else {
getSupportFragmentManager()
.beginTransaction()
.show(offlineAlertFragment)
.commit();
}
// Change the map
if (mMapType == AsamConstants.MAP_TYPE_OFFLINE_110M) {
if (offlineMap != null) offlineMap.clear();
offlineMap = new OfflineMap(this, mMapUI, offlineGeometries);
} else {
if (offlineMap != null) {
offlineMap.clear();
offlineMap = null;
}
mMapUI.setMapType(mMapType);
}
// Update shared preferences
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(AsamConstants.MAP_TYPE_KEY, mMapType);
editor.commit();
}
@Override
public void onOfflineFeaturesLoaded(Collection<Geometry> offlineGeometries) {
this.offlineGeometries = offlineGeometries;
if (offlineMap110mMenuItem != null) offlineMap110mMenuItem.setVisible(true);
if (offlineMap == null && mMapType == AsamConstants.MAP_TYPE_OFFLINE_110M) {
if (offlineMap != null) offlineMap.clear();
offlineMap = new OfflineMap(this, mMapUI, offlineGeometries);
}
}
@Override
public void onOfflineBannerClick() {
onMapTypeChanged(AsamConstants.MAP_TYPE_OFFLINE_110M);
supportInvalidateOptionsMenu();
}
}