package com.example.Maps011;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import org.json.JSONObject;
 
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
 
import com.google.android.gms.maps.model.LatLng;
 
public class Geo02 extends FragmentActivity 
{
 
	GoogleMap map;
	ArrayList markerPoints;
 
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.geo02_layout);
 
		// Initializing
		markerPoints = new ArrayList();
 
		// Getting reference to SupportMapFragment of the activity_main
		SupportMapFragment fm = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
 
		// Getting Map for the SupportMapFragment
		map = fm.getMap();
 
		if(map!=null)
		{
 
			// Enable MyLocation Button in the Map
			map.setMyLocationEnabled(true);
			
			//http://www.androidtrainee.com/drawing-driving-route-directions-between-two-locations-using-google-directions-in-google-map-android-api-v2/
 
					 
			// Getting URL to the Google Directions API
			String url = getDirectionsUrl();
						 
			DownloadTask downloadTask = new DownloadTask();
					 
			// Start downloading json data from Google Directions API
			downloadTask.execute(url);
				
			
		}
	}
 
	private String getDirectionsUrl()
	{
		
//		https://www.google.fr/maps/place/47+Chemin+du+Chapitre,+31100+Toulouse/@43.5592555,1.4104784,18.5z/
//			data=!4m19!1m13!4m12!1m6!1m2!1s0x12ade1d1de291969:0x406f69c2f3be360!2sR%C3%A9almont,+France!2m2!1d2.18884!2d43.776621!1m3!2m2!1d1.
//			4105353!2d43.5590191!3e0!3m4!1s0x12aebbd160c93441:0xf7aa4d53c02c4ec9!8m2!3d43.5590204!4d1.4105316
		
	
		
		// Origin of route
		String str_origin = "origin=" + "1 rue      du stade realmont"; 
				 
		// Destination of route
		String str_dest = "destination=" + "55 chemin du chapitre toulouse";
		
		// Sensor enabled
		String sensor = "sensor=false";
				 
		// Building the parameters to the web service
		String parameters = str_origin+"&"+str_dest+"&"+sensor;
		
		parameters = parameters.replaceAll(" ", "+");
		
		/*
		try {
			parameters = URLEncoder.encode(parameters, "utf-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
				 
		// Output format
		String output = "json";
				 
		// Building the url to the web service
		String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
		
		//url = "https://maps.googleapis.com/maps/api/directions/json?origin=Disneyland&destination=Universal+Studios+Hollywood";
		
		//url = "https://maps.googleapis.com/maps/api/directions/json?origin=Toulouse&destination=albi";
		
		//url = "https://maps.googleapis.com/maps/api/directions/json?origin=1+rue+du+stade+realmont&destination=55+chemin+du+chapitre+toulouse";
		
		
		///// pour faire un test sur le service web de google 
		//http://maps.googleapis.com/maps/api/directions/json?origin=(MY
		
		return url;
		
	}
	
	private String getDirectionsUrl(LatLng origin,LatLng dest)
	{
 
		// Origin of route
		String str_origin = "origin="+origin.latitude+","+origin.longitude;
		 
		// Destination of route
		String str_dest = "destination="+dest.latitude+","+dest.longitude;
		 
		// Sensor enabled
		String sensor = "sensor=false";
		 
		// Building the parameters to the web service
		String parameters = str_origin+"&"+str_dest+"&"+sensor;
		 
		// Output format
		String output = "json";
		 
		// Building the url to the web service
		String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
		 
		return url;
	}
 
	/** A method to download json data from url */
	private String downloadUrl(String strUrl) throws IOException
	{
		String data = "";
		InputStream iStream = null;
		HttpURLConnection urlConnection = null;
		try{
		URL url = new URL(strUrl);
		 
		// Creating an http connection to communicate with url
		urlConnection = (HttpURLConnection) url.openConnection();
		 
		// Connecting to url
		urlConnection.connect();
		 
		// Reading data from url
		iStream = urlConnection.getInputStream();
		 
		BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
		 
		StringBuffer sb = new StringBuffer();
		 
		String line = "";
		while( ( line = br.readLine()) != null){
		sb.append(line);
		}
		 
		data = sb.toString();
		 
		br.close();
		 
		}catch(Exception e){
		Log.d("Exception while downloading url", e.toString());
		}finally{
		iStream.close();
		urlConnection.disconnect();
		}
		return data;
	}
 
	// Fetches data from url passed
	private class DownloadTask extends AsyncTask<String, Void, String>
	{
 
		// Downloading data in non-ui thread
		@Override
		protected String doInBackground(String... url) 
		{
		 
			// For storing data from web service
			String data = "";
			 
			try{
			// Fetching the data from web service
			data = downloadUrl(url[0]);
			}catch(Exception e){
			Log.d("Background Task",e.toString());
			}
			return data;
		}
 
		// Executes in UI thread, after the execution of // doInBackground()

		@Override protected void onPostExecute(String result) 
		{
			super.onPostExecute(result);
 
			ParserTask parserTask = new ParserTask();
 
			// Invokes the thread for parsing the JSON data
			parserTask.execute(result);
 
		}
	}
 
	/** A class to parse the Google Places in JSON format */
	private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>> >
	{
 
		// Parsing the data in non-ui thread
		@Override
		protected List<List<HashMap<String, String>>> doInBackground(String... jsonData)
		{
 
			JSONObject jObject;
			List<List<HashMap<String, String>>> routes = null;
 
			try{
			jObject = new JSONObject(jsonData[0]);
			DirectionsJSONParser_bis parser = new DirectionsJSONParser_bis();
			 
			// Starts parsing data
			routes = parser.parse(jObject);
			}catch(Exception e){
			e.printStackTrace();
			}
			return routes;
		}
 
		// Executes in UI thread, after the parsing process
		@Override
		protected void onPostExecute(List<List<HashMap<String, String>>> result) 
		{

			ArrayList points = null;
			PolylineOptions lineOptions = null;
			MarkerOptions markerOptions = new MarkerOptions();
 
			// Traversing through all the routes
			for(int i=0;i<result.size();i++)
			{

				points = new ArrayList();
				lineOptions = new PolylineOptions();
 
				// Fetching i-th route
				List<HashMap<String, String>> path = result.get(i);
 
				// Fetching all the points in i-th route
				for(int j=0;j <path.size();j++)
				{
					HashMap<String,String> point = path.get(j);
					 
					double lat = Double.parseDouble(point.get("lat"));
					double lng = Double.parseDouble(point.get("lng"));
					LatLng position = new LatLng(lat, lng);
					 
					points.add(position);
					
					MarkerOptions options = new MarkerOptions();
					
					if(j == 0)
					{
						// Creating MarkerOptions
					
						
						// Setting the position of the marker
						options.position(position);
						options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
						map.addMarker(options);
						
		                //map.animateCamera(CameraUpdateFactory.newLatLng(position));
						
					}
					
					if(j == path.size()-1 )
					{
						// Creating MarkerOptions
					
						
						// Setting the position of the marker
						options.position(position);
						options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
						map.addMarker(options);
						
						//bounds  = new google.maps.LatLngBounds();
						//map.getBounds();
						
						map.moveCamera(CameraUpdateFactory.newLatLngZoom(position, 7));
					}
					
					
					
				}
 
				// Adding all the points in the route to LineOptions
				lineOptions.addAll(points);
				lineOptions.width(2);
				lineOptions.color(Color.RED);
 
			}
 
			// Drawing polyline in the Google Map for the i-th route
			map.addPolyline(lineOptions);
			
			//http://www.svennerberg.com/2008/11/bounding-box-in-google-maps/
			
			
		}


	}
 

}


class DirectionsJSONParser_bis 
{
	 
	/** Receives a JSONObject and returns a list of lists containing latitude and longitude */
	public List<List<HashMap<String,String>>> parse(JSONObject jObject)
	{
 
		List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>() ;
		JSONArray jRoutes = null;
		JSONArray jLegs = null;
		JSONArray jSteps = null;
 
		try {
 
				jRoutes = jObject.getJSONArray("routes");
 
				/** Traversing all routes */
				for(int i=0;i<jRoutes.length();i++)
				{
					jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
					List path = new ArrayList<HashMap<String, String>>();
 
					/** Traversing all legs */
					for(int j=0;j<jLegs.length();j++)
					{
						jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
 
						/** Traversing all steps */
						for(int k=0;k<jSteps.length();k++)
						{
							String polyline = "";
							polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
							List list = decodePoly(polyline);
 
							/** Traversing all points */
							for(int l=0;l <list.size();l++)
							{
								HashMap<String, String> hm = new HashMap<String, String>();
								hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) );
								hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude) );
								path.add(hm);
							}
						}
						
						routes.add(path);
					}
				}
 
		} 
		catch (JSONException e) 
		{
			e.printStackTrace();
		}catch (Exception e)
		{
		}
 
		return routes;
	}
 
	/**
	* Method to decode polyline points
	* Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
	* */
	private List decodePoly(String encoded) 
	{
 
			List poly = new ArrayList();
			int index = 0, len = encoded.length();
			int lat = 0, lng = 0;
			 
			while (index < len) {
			int b, shift = 0, result = 0;
			do {
			b = encoded.charAt(index++) - 63;
			result |= (b & 0x1f) << shift;
			shift += 5;
			} while (b >= 0x20);
			int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lat += dlat;
			 
			shift = 0;
			result = 0;
			do {
			b = encoded.charAt(index++) - 63;
			result |= (b & 0x1f) << shift;
			shift += 5;
			} while (b >= 0x20);
			int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lng += dlng;
			 
			LatLng p = new LatLng((((double) lat / 1E5)),
			(((double) lng / 1E5)));
			poly.add(p);
			}
			 
			return poly;
	}
}