/**
*
*/
package net.osmand.plus.activities.search;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import net.osmand.Algoritms;
import net.osmand.OsmAndFormatter;
import net.osmand.data.TransportRoute;
import net.osmand.data.TransportStop;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.TransportIndexRepository;
import net.osmand.plus.TransportIndexRepository.RouteInfoLocation;
import net.osmand.plus.activities.OsmandApplication;
import net.osmand.plus.activities.TransportRouteHelper;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* @author Maxim Frolov
*
*/
public class SearchTransportActivity extends ListActivity {
public static final String LAT_KEY = "lat"; //$NON-NLS-1$
public static final String LON_KEY = "lon"; //$NON-NLS-1$
private Button searchTransportLevel;
private TextView searchArea;
private TransportIndexRepository repo;
private final static int finalZoom = 13;
private final static int initialZoom = 17;
private int zoom = initialZoom;
private ProgressBar progress;
private Thread thread;
private LatLon lastKnownMapLocation;
private LatLon destinationLocation;
private LatLon selectedDestinationLocation;
private TransportStopAdapter stopsAdapter;
private TransportRouteAdapter intermediateListAdapater;
private SharedPreferences settings;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
settings = OsmandSettings.getPrefs(this);
Bundle extras = getIntent().getExtras();
if(extras != null && extras.containsKey(LAT_KEY) && extras.containsKey(LON_KEY)){
lastKnownMapLocation = new LatLon(extras.getDouble(LAT_KEY), extras.getDouble(LON_KEY));
} else {
lastKnownMapLocation = OsmandSettings.getLastKnownMapLocation(settings);
}
setContentView(R.layout.search_transport);
searchTransportLevel = (Button) findViewById(R.id.SearchTransportLevelButton);
searchTransportLevel.setText(R.string.search_POI_level_btn);
searchTransportLevel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!isRouteCalculated()) {
if (isSearchFurtherAvailable()) {
zoom--;
searchTransport();
}
} else {
intermediateListAdapater.clear();
intermediateListAdapater.add(null);
searchTransport();
}
}
});
searchArea = (TextView) findViewById(R.id.SearchAreaText);
progress = (ProgressBar) findViewById(R.id.ProgressBar);
progress.setVisibility(View.INVISIBLE);
stopsAdapter = new TransportStopAdapter(new ArrayList<RouteInfoLocation>());
setListAdapter(stopsAdapter);
ListView intermediateList = (ListView) findViewById(R.id.listView);
intermediateListAdapater = new TransportRouteAdapter(TransportRouteHelper.getInstance().getRoute());
intermediateList.setAdapter(intermediateListAdapater);
if(intermediateList.getCount() == 0){
intermediateListAdapater.add(null);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
ArrayList<RouteInfoLocation> lastEditedRoute = new ArrayList<RouteInfoLocation>();
for(int i= 0; i< intermediateListAdapater.getCount(); i++){
RouteInfoLocation item = intermediateListAdapater.getItem(i);
if(item != null){
lastEditedRoute.add(item);
}
}
TransportRouteHelper.getInstance().setRoute(lastEditedRoute);
}
@Override
protected void onResume() {
super.onResume();
LatLon pointToNavigate = OsmandSettings.getPointToNavigate(OsmandSettings.getPrefs(this));
if(!Algoritms.objectEquals(pointToNavigate, this.destinationLocation)){
destinationLocation = pointToNavigate;
selectedDestinationLocation = destinationLocation;
searchTransport();
}
}
public String getSearchArea(){
return " < " + 125 * (1 << (17 - zoom)) + " " + getString(R.string.m); //$NON-NLS-1$//$NON-NLS-2$
}
public boolean isSearchFurtherAvailable() {
return zoom >= finalZoom;
}
public void searchTransport(){
// use progress
stopsAdapter.clear();
searchArea.setText(getSearchArea());
boolean routeCalculated = isRouteCalculated();
searchTransportLevel.setEnabled(false);
if (!routeCalculated && getLocationToStart() != null) {
final LatLon locationToStart = getLocationToStart();
final LatLon locationToGo = getLocationToGo();
List<TransportIndexRepository> rs = ((OsmandApplication)getApplication()).getResourceManager().searchTransportRepositories(locationToStart.getLatitude(),
locationToStart.getLongitude());
if(!rs.isEmpty()){
repo = rs.get(0);
progress.setVisibility(View.VISIBLE);
synchronized (this) {
final Thread previousThread = thread;
thread = new Thread(new Runnable() {
@Override
public void run() {
if (previousThread != null) {
try {
previousThread.join();
} catch (InterruptedException e) {
}
}
List<RouteInfoLocation> res = repo.searchTransportRouteStops(locationToStart.getLatitude(), locationToStart
.getLongitude(), locationToGo, zoom);
updateUIList(res);
}
}, "SearchingTransport"); //$NON-NLS-1$
thread.start();
}
} else {
repo = null;
}
} else {
updateSearchMoreButton();
}
}
protected void updateUIList(final List<RouteInfoLocation> stopsList){
runOnUiThread(new Runnable(){
@Override
public void run() {
stopsAdapter.setNewModel(stopsList);
updateSearchMoreButton();
searchArea.setText(getSearchArea());
progress.setVisibility(View.INVISIBLE);
}});
}
private void updateSearchMoreButton() {
if (!isRouteCalculated()) {
searchTransportLevel.setEnabled(isSearchFurtherAvailable());
searchTransportLevel.setText(R.string.search_POI_level_btn);
} else {
searchTransportLevel.setEnabled(true);
searchTransportLevel.setText(R.string.transport_search_again);
}
}
public String getInformation(RouteInfoLocation route, List<TransportStop> stops, int position, boolean part){
StringBuilder text = new StringBuilder(200);
double dist = 0;
int ind = 0;
int stInd = stops.size();
int eInd = stops.size();
for (TransportStop s : stops) {
if (s == route.getStart()) {
stInd = ind;
}
if (s == route.getStop()) {
eInd = ind;
}
if (ind > stInd && ind <= eInd) {
dist += MapUtils.getDistance(stops.get(ind - 1).getLocation(), s.getLocation());
}
ind++;
}
text.append(getString(R.string.transport_route_distance)).append(" ").append(OsmAndFormatter.getFormattedDistance((int) dist, this)); //$NON-NLS-1$/
if(!part){
text.append(", ").append(getString(R.string.transport_stops_to_pass)).append(" ").append(eInd - stInd); //$NON-NLS-1$ //$NON-NLS-2$
LatLon endStop = getEndStop(position - 1);
if (endStop != null) {
String before = OsmAndFormatter.getFormattedDistance((int) MapUtils.getDistance(endStop, route.getStart().getLocation()), SearchTransportActivity.this);
text.append(", ").append(getString(R.string.transport_to_go_before)).append(" ").append(before); //$NON-NLS-2$//$NON-NLS-1$
}
LatLon stStop = getStartStop(position + 1);
if (stStop != null) {
String after = OsmAndFormatter.getFormattedDistance((int) MapUtils.getDistance(stStop, route.getStop().getLocation()), SearchTransportActivity.this);
text.append(", ").append(getString(R.string.transport_to_go_after)).append(" ").append(after); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return text.toString();
}
public void onListItemClick(ListView parent, View v, int position, long id) {
final RouteInfoLocation item = ((TransportStopAdapter)getListAdapter()).getItem(position);
Builder builder = new AlertDialog.Builder(this);
List<String> items = new ArrayList<String>();
final List<TransportStop> stops = item.getDirection() ? item.getRoute().getForwardStops() : item.getRoute().getBackwardStops();
LatLon locationToGo = getLocationToGo();
LatLon locationToStart = getLocationToStart();
builder.setTitle(getString(R.string.transport_stop_to_go_out)+"\n"+getInformation(item, stops, getCurrentRouteLocation(), true)); //$NON-NLS-1$
int ind = 0;
for(TransportStop st : stops){
StringBuilder n = new StringBuilder(50);
n.append(ind++);
if(st == item.getStop()){
n.append("!! "); //$NON-NLS-1$
} else {
n.append(". "); //$NON-NLS-1$
}
String name = st.getName(OsmandSettings.usingEnglishNames(settings));
if(locationToGo != null){
n.append(name).append(" - ["); //$NON-NLS-1$
n.append(OsmAndFormatter.getFormattedDistance((int) MapUtils.getDistance(locationToGo, st.getLocation()), SearchTransportActivity.this)).append("]"); //$NON-NLS-1$
} else if(locationToStart != null){
n.append("[").append(OsmAndFormatter.getFormattedDistance((int) MapUtils.getDistance(locationToStart, st.getLocation()), SearchTransportActivity.this)).append("] - "); //$NON-NLS-1$ //$NON-NLS-2$
n.append(name);
} else {
n.append(name);
}
items.add(n.toString());
}
builder.setItems(items.toArray(new String[items.size()]), new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
int i = which;
if(i >= 0){
TransportStop stop = stops.get(i);
showContextMenuOnStop(stop, item, i);
}
}
});
builder.show();
}
public void showContextMenuOnStop(final TransportStop stop, final RouteInfoLocation route, final int stopInd) {
Builder b = new AlertDialog.Builder(this);
b.setItems(new String[] { getString(R.string.transport_finish_search), getString(R.string.transport_search_before), getString(R.string.transport_search_after) },
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int currentRouteCalculation = getCurrentRouteLocation();
route.setStop(stop);
route.setStopNumbers(stopInd);
if (which == 0) {
intermediateListAdapater.insert(route, currentRouteCalculation);
intermediateListAdapater.remove(null);
currentRouteCalculation = -1;
} else if (which == 1) {
intermediateListAdapater.insert(route, currentRouteCalculation + 1);
} else if (which == 2) {
intermediateListAdapater.insert(route, currentRouteCalculation);
}
// layout
zoom = initialZoom;
searchTransport();
}
});
b.show();
}
public void showContextMenuOnRoute(final RouteInfoLocation route, final int routeInd) {
Builder b = new AlertDialog.Builder(this);
List<TransportStop> stops = route.getDirection() ? route.getRoute().getForwardStops() : route.getRoute().getBackwardStops();
boolean en = OsmandSettings.usingEnglishNames(settings);
String info = getInformation(route, stops, routeInd, false);
StringBuilder txt = new StringBuilder(300);
txt.append(info);
boolean start = false;
for(TransportStop s : stops){
if(s == route.getStart()){
start = true;
}
if(start){
txt.append("\n").append(getString(R.string.transport_Stop)).append(" : ").append(s.getName(en)); //$NON-NLS-1$ //$NON-NLS-2$
}
if(s == route.getStop()){
break;
}
}
b.setMessage(txt.toString());
b.setPositiveButton(getString(R.string.default_buttons_ok), null);
b.setNeutralButton(getString(R.string.transport_search_before), new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
int toInsert = routeInd;
int c = getCurrentRouteLocation();
if(c >= 0 && c < routeInd){
toInsert --;
}
intermediateListAdapater.remove(null);
intermediateListAdapater.insert(null, routeInd);
zoom = initialZoom;
searchTransport();
}
});
b.setNegativeButton(getString(R.string.transport_search_after), new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
int toInsert = routeInd;
int c = getCurrentRouteLocation();
if(c > routeInd || c == -1){
toInsert ++;
}
intermediateListAdapater.remove(null);
intermediateListAdapater.insert(null, toInsert);
zoom = initialZoom;
searchTransport();
}
});
b.show();
}
public int getCurrentRouteLocation(){
return intermediateListAdapater.getPosition(null);
}
public boolean isRouteCalculated(){
return getCurrentRouteLocation() == -1;
}
public LatLon getLocationToStart() {
return getEndStop(getCurrentRouteLocation() - 1);
}
public LatLon getLocationToGo() {
return getStartStop(getCurrentRouteLocation() + 1);
}
public LatLon getStartStop(int position){
if(position == intermediateListAdapater.getCount()){
return selectedDestinationLocation;
}
RouteInfoLocation item = intermediateListAdapater.getItem(position);
if(item == null){
return getStartStop(position + 1);
}
return item.getStart().getLocation();
}
public LatLon getEndStop(int position){
if(position == -1){
return lastKnownMapLocation;
}
RouteInfoLocation item = intermediateListAdapater.getItem(position);
if(item == null){
return getEndStop(position -1);
}
return item.getStop().getLocation();
}
class TransportStopAdapter extends ArrayAdapter<RouteInfoLocation> {
private List<RouteInfoLocation> model;
TransportStopAdapter(List<RouteInfoLocation> list) {
super(SearchTransportActivity.this, R.layout.search_transport_list_item, list);
model = list;
}
public void setNewModel(List<RouteInfoLocation> stopsList) {
this.model = stopsList;
setNotifyOnChange(false);
((TransportStopAdapter) getListAdapter()).clear();
for (RouteInfoLocation obj : stopsList) {
this.add(obj);
}
this.notifyDataSetChanged();
setNotifyOnChange(true);
}
public List<RouteInfoLocation> getModel() {
return model;
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.search_transport_list_item, parent, false);
}
LatLon locationToGo = getLocationToGo();
LatLon locationToStart = getLocationToStart();
TextView label = (TextView) row.findViewById(R.id.label);
TextView distanceLabel = (TextView) row.findViewById(R.id.distance);
ImageView icon = (ImageView) row.findViewById(R.id.search_icon);
RouteInfoLocation stop = getItem(position);
TransportRoute route = stop.getRoute();
StringBuilder labelW = new StringBuilder(150);
labelW.append(route.getType()).append(" ").append(route.getRef()); //$NON-NLS-1$
labelW.append(" - ["); //$NON-NLS-1$
if (locationToGo != null) {
labelW.append(OsmAndFormatter.getFormattedDistance(stop.getDistToLocation(), SearchTransportActivity.this));
} else {
labelW.append(getString(R.string.transport_search_none));
}
labelW.append("]\n").append(route.getName(OsmandSettings.usingEnglishNames(settings))); //$NON-NLS-1$
label.setText(labelW.toString());
// TODO icons
if (locationToGo != null && stop.getDistToLocation() < 400) {
icon.setImageResource(R.drawable.opened_poi);
} else {
icon.setImageResource(R.drawable.poi);
}
int dist = locationToStart == null ? 0 : (int) (MapUtils.getDistance(stop.getStart().getLocation(), locationToStart));
distanceLabel.setText(" " + OsmAndFormatter.getFormattedDistance(dist, SearchTransportActivity.this)); //$NON-NLS-1$
return (row);
}
}
class TransportRouteAdapter extends ArrayAdapter<RouteInfoLocation> {
TransportRouteAdapter(List<RouteInfoLocation> list) {
super(SearchTransportActivity.this, R.layout.search_transport_route_item, list);
}
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
final RouteInfoLocation info = getItem(position);
if(info == null){
TextView text = new TextView(getContext());
LatLon st = getStartStop(position + 1);
LatLon end = getEndStop(position - 1);
if(st != null && end != null){
int dist = (int) MapUtils.getDistance(st, end);
text.setText(MessageFormat.format(getString(R.string.transport_searching_route), OsmAndFormatter.getFormattedDistance(dist, SearchTransportActivity.this)));
} else {
text.setText(getString(R.string.transport_searching_transport));
}
text.setTextSize(21);
text.setTypeface(null, Typeface.ITALIC);
text.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(intermediateListAdapater.getCount() > 1){
intermediateListAdapater.remove(null);
searchTransport();
} else {
if(selectedDestinationLocation == null){
selectedDestinationLocation = destinationLocation;
} else {
selectedDestinationLocation = null;
}
searchTransport();
}
}
});
return text;
}
int currentRouteLocation = getCurrentRouteLocation();
if (row == null || row instanceof TextView) {
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.search_transport_route_item, parent, false);
}
TextView label = (TextView) row.findViewById(R.id.label);
ImageButton icon = (ImageButton) row.findViewById(R.id.remove);
TransportRoute route = info.getRoute();
icon.setVisibility(View.VISIBLE);
StringBuilder labelW = new StringBuilder(150);
labelW.append(route.getType()).append(" ").append(route.getRef()); //$NON-NLS-1$
boolean en = OsmandSettings.usingEnglishNames(settings);
labelW.append(" : ").append(info.getStart().getName(en)).append(" - ").append(info.getStop().getName(en)); //$NON-NLS-1$ //$NON-NLS-2$
// additional information if route is calculated
if (currentRouteLocation == -1) {
labelW.append(" ("); //$NON-NLS-1$
labelW.append(info.getStopNumbers()).append(" ").append(getString(R.string.transport_stops)).append(", "); //$NON-NLS-1$ //$NON-NLS-2$
int startDist = (int) MapUtils.getDistance(getEndStop(position - 1), info.getStart().getLocation());
labelW.append(getString(R.string.transport_to_go_before)).append(" ").append(OsmAndFormatter.getFormattedDistance(startDist, SearchTransportActivity.this)); //$NON-NLS-1$
if (position == getCount() - 1) {
LatLon stop = getStartStop(position + 1);
if(stop != null) {
int endDist = (int) MapUtils.getDistance(stop, info.getStop().getLocation());
labelW.append(", ").append(getString(R.string.transport_to_go_after)).append(" ").append(OsmAndFormatter.getFormattedDistance(endDist, SearchTransportActivity.this)); //$NON-NLS-1$ //$NON-NLS-2$
}
}
labelW.append(")"); //$NON-NLS-1$
}
label.setText(labelW.toString());
icon.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
int p = position;
intermediateListAdapater.remove(null);
if(!isRouteCalculated() && getCurrentRouteLocation() < p){
p--;
}
intermediateListAdapater.insert(null, p);
intermediateListAdapater.remove(info);
intermediateListAdapater.notifyDataSetChanged();
zoom = initialZoom;
searchTransport();
}
});
View.OnClickListener clickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
showContextMenuOnRoute(info, position);
}
};
label.setOnClickListener(clickListener);
return row;
}
}
}