package com.yanp.way.asyncTasks;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.PolylineOptions;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.yanp.way.Constants;
import com.yanp.way.Decoder;
import com.yanp.way.R;
import com.yanp.way.route.Route;
import com.yanp.way.route.activity.CreateRoute;
import com.yanp.way.route.downloaded.DirectionsResponse;
import com.yanp.way.route.downloaded.Legs;
/*
* R????cup????re les d????tails d'un trajet via l'API DirectionsResponse
*/
/**
* Get the details of a route using Google DirectionsResponse API, draw this route on the map.
* @author YPierru
*
*/
public class CallsDirRespAPIAndDrawRoute extends AsyncTask<Void, Void, DirectionsResponse> {
private String url_pattern;
private ProgressDialog progressDialog;
private Route route;
private ArrayList<Marker> listMarkers;
private CreateRoute createRouteInstance;
private GoogleMap googleMap;
/**
*
* @param createRouteInstance - Reference of the activity where the route will be draw
* @param route - The route, this object will be filled with data here
* @param listMarkers - The list of the markers created on the map by the user
* @param googleMap - The Google Map
*/
public CallsDirRespAPIAndDrawRoute(CreateRoute createRouteInstance, Route route,ArrayList<Marker> listMarkers, GoogleMap googleMap) {
this.createRouteInstance=createRouteInstance;
this.progressDialog = new ProgressDialog(createRouteInstance);
this.route=route;
this.listMarkers=listMarkers;
this.googleMap=googleMap;
this.url_pattern=this.createRouteInstance.getResources().getString(R.string.url_pattern_directionsapi)+"&language="+Constants.CURRENT_LANGUAGE.getLanguage();
}
/**
* Display the informative message during the wait
*/
protected void onPreExecute() {
super.onPreExecute();
this.progressDialog.setMessage(this.createRouteInstance.getResources().getString(R.string.drawing_in_progress)+"...");
this.progressDialog.show();
}
protected DirectionsResponse doInBackground(Void... arg0) {
String str=constructStringPoints();
DirectionsResponse dataFromDirRespAPI = callAPI(str);
return dataFromDirRespAPI;
}
/**
* Transform a list of LatLng points, in a String with the pattern : "point1.x,point1.y|point2.x,point2.y|...|pointN.x,pointN.y"
* @return the String of the points
*/
private String constructStringPoints(){
/**
* First, we get the LatLng positions of the markers.
*/
ArrayList<LatLng>listIntermediaryPoints = this.route.getListMarkersLatLng();
/**
* The first and last points will be in the URL, we must remove them here.
*/
listIntermediaryPoints.remove(0);
listIntermediaryPoints.remove(listIntermediaryPoints.size() - 1);
String intermiediaryPoints = "&waypoints=";
/**
* Construction of the String
*/
for (int i = 0; i < listIntermediaryPoints.size(); i++) {
intermiediaryPoints += listIntermediaryPoints.get(i).latitude + ","
+ listIntermediaryPoints.get(i).longitude;
if (i + 1 < listIntermediaryPoints.size()) {
intermiediaryPoints += "|";
}
}
return intermiediaryPoints;
}
/**
* Construct the URL, call the API, parse the result
* @param intermediaryPointsString
* @return The JAVA struct from the JSON
*/
private DirectionsResponse callAPI(String intermediaryPointsString){
DirectionsResponse dataFromDirRespAPI = null;
/**
* See https://developers.google.com/maps/documentation/directions/#RequestParameters
*/
String mode = "driving";
LatLng origin = this.route.getListMarkersLatLng().get(0);
LatLng destination = this.route.getListMarkersLatLng().get(this.route.getListMarkersLatLng().size()-1);
URL url = null;
try {
url = new URL(this.url_pattern
+ "&mode=" + mode
+ "&origin=" + origin.latitude + ","+ origin.longitude
+ "&destination=" + destination.latitude + ","+ destination.longitude
+ intermediaryPointsString);
/**
* Here we get the data from the API.
* Then the JSON is convert to a JAVA structure (DirectionsResponse)
*/
InputStream is = url.openStream();
String jsonData = IOUtils.toString(is);
//Log.d("DEBUUUUUUUUG", jsonData);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
dataFromDirRespAPI = gson.fromJson(jsonData, DirectionsResponse.class);
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return dataFromDirRespAPI;
}
protected void onPostExecute(DirectionsResponse dataFromDirRespAPI) {
super.onPostExecute(dataFromDirRespAPI);
/**
* We add the data to the route
*/
this.route.getListSegment().clear();
this.route.getListSegment().add(dataFromDirRespAPI);
replaceMarkers(dataFromDirRespAPI);
drawRouteOnMap(dataFromDirRespAPI);
writeRouteDetailsOnActionBar();
this.progressDialog.dismiss();
}
/**
* Replace the markers on the road.
* @param dataFromDirRespAPI
*/
private void replaceMarkers(DirectionsResponse dataFromDirRespAPI){
List<Legs> listLegs = dataFromDirRespAPI.getRoutes().get(0).getLegs();
ArrayList<LatLng> tmpPoints = new ArrayList<LatLng>();
for (int i = 0; i < listLegs.size(); i++) {
tmpPoints.add(new LatLng(listLegs.get(i).getStart_location().getLat(),
listLegs.get(i).getStart_location().getLng()));
if (i + 1 == listLegs.size()) {
tmpPoints.add(new LatLng(listLegs.get(i).getEnd_location().getLat(),
listLegs.get(i).getEnd_location().getLng()));
}
}
this.route.setListMarkersLatLng(tmpPoints);
for (int i = 0; i < this.listMarkers.size(); i++) {
this.listMarkers.get(i).setPosition(tmpPoints.get(i));
}
}
/**
* Draw the route on the Google Map
*/
private void drawRouteOnMap(DirectionsResponse dataFromDirRespAPI){
/**
* We decode the points of the route
*/
ArrayList<LatLng> listOverviewPolylinePoints = Decoder.decodePoly(dataFromDirRespAPI.getRoutes().get(0).getOverview_polyline().getPoints());
PolylineOptions options = new PolylineOptions()
.geodesic(false)
.width(Constants.WIDTH_POLYLINE)
.color(Constants.COLOR_POLYLINE);
for (int i = 0; i < listOverviewPolylinePoints.size(); i++) {
options.add(listOverviewPolylinePoints.get(i));
}
this.createRouteInstance.setPolyline(googleMap.addPolyline(options));
this.route.setPointsWhoDrawsPolylineLatLng(listOverviewPolylinePoints);
this.route.setValidate(true);
}
/**
* Write the details of the route (distance, duration), on the action bar
*/
private void writeRouteDetailsOnActionBar(){
String strSubtitle = "";
double dist = route.getDistTotal();
if (dist < 1000) {
strSubtitle += ((int) dist + "m");
} else {
strSubtitle += ((dist / 1000) + "Km");
}
int dureeSecond = route.getDureeTotal();
int heures = (dureeSecond / 3600);
int minutes = ((dureeSecond % 3600) / 60);
if (heures == 0) {
strSubtitle += " - ~" + (minutes + "min");
} else {
strSubtitle += " - ~" + (heures + "h" + minutes + "min");
}
this.createRouteInstance.getActionBar().setSubtitle(strSubtitle);
}
}