package com.example.Maps010;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Intent;
import android.graphics.Color;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.google.android.gms.identity.intents.Address;
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 com.google.android.gms.vision.barcode.Barcode.GeoPoint;




//http://wptrafficanalyzer.in/blog/driving-distance-and-travel-time-duration-between-two-locations-in-google-map-android-api-v2/

public class MainActivity extends FragmentActivity {

	GoogleMap map;
	ArrayList<LatLng> markerPoints;
	TextView tvDistanceDuration;
	
	ToggleButton tbMode;
	
	int DirectionMode = 0 ;
	int MODE_DRIVING = 1;
	int MODE_WALKING = 2;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.navigation_layout);
		
		tvDistanceDuration = (TextView) findViewById(R.id.tv_distance_time);
		
		// Initializing 
		markerPoints = new ArrayList<LatLng>();
		
		// Getting reference to SupportMapFragment of the activity_main
		SupportMapFragment fm = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
		
		// Getting Map for the SupportMapFragment
		map = fm.getMap();
		
		// Enable MyLocation Button in the Map
		map.setMyLocationEnabled(true);		
		
		
		map.setMyLocationEnabled(true);
		map.setIndoorEnabled(true);
		map.getUiSettings().setZoomControlsEnabled(true);
		map.getUiSettings().setMyLocationButtonEnabled(true);
		map.getUiSettings().setCompassEnabled(true);
		map.getUiSettings().setAllGesturesEnabled(true);
		
		
		tbMode = (ToggleButton) findViewById(R.id.tbMode);
		tbMode.setOnClickListener(new OnClickListener() 
		{

			@Override
			public void onClick(View v) 
			{
				// TODO Auto-generated method stub
				Toast.makeText(getBaseContext(), "No Points", Toast.LENGTH_SHORT).show();
				
				if (tbMode.isChecked()) 
				{
					DirectionMode = 1;
				} 
				else 
				{
					DirectionMode = 2;
				}
				
				
			}

		});
		

		tbMode.setChecked(true);
		DirectionMode = 1;
		
		// Setting onclick event listener for the map
		map.setOnMapClickListener(new OnMapClickListener() {
			
			@Override
			public void onMapClick(LatLng point) {
				
				// Already two locations				
				if(markerPoints.size()>1){
					markerPoints.clear();
					map.clear();					
				}
				
				// Adding new item to the ArrayList
				markerPoints.add(point);				
				
				// Creating MarkerOptions
				MarkerOptions options = new MarkerOptions();
				
				// Setting the position of the marker
				options.position(point);
				
				/** 
				 * For the start location, the color of marker is GREEN and
				 * for the end location, the color of marker is RED.
				 */
				if(markerPoints.size()==1){
					options.title("destinationPositionTitle");
					Double a = point.latitude;
					Double b = point.longitude;
					
					String str1 = String.valueOf(a);
					String str2 = String.valueOf(b);
					String str = str1 +" " + str2; 

					
					options.snippet(str);
					
					
					options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
				}else if(markerPoints.size()==2){
					options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
				}
							
				
				// Add new marker to the Google Map Android API V2
				map.addMarker(options);
				
		/*		
				MarkerOptions mDestination = new MarkerOptions()
						.position(destinationPosition)
						.title(destinationPositionTitle)
						.snippet(destinationPositionSnippet)
						.icon(BitmapDescriptorFactory.fromResource(R.drawable.pin1));

				MarkerOptions mStart = new MarkerOptions()
						.position(startPosition)
						.title(startPositionTitle)
						.snippet(startPositionSnippet)
						.icon(BitmapDescriptorFactory.fromResource(R.drawable.pin2));

				mMap.addMarker(mDestination);
				mMap.addMarker(mStart);
		*/		
				
				
				
				
				// Checks, whether start and end locations are captured
				if(markerPoints.size() >= 2){					
					LatLng origin = markerPoints.get(0);
					LatLng dest = markerPoints.get(1);
					
					// Getting URL to the Google Directions API
					String url = getDirectionsUrl(origin, dest);				
					
					DownloadTask downloadTask = new DownloadTask();
					
					// Start downloading json data from Google Directions API
					downloadTask.execute(url);
				}
				
			}
		});
		
		
		String lieu = getCompleteAddressString(43.7717, 2.1848); 
		
		getLocationFromAddress(lieu);
		
	/*	
	      Geocoder coder = new Geocoder(this);
	      try {
	          ArrayList<Address> adresses = (ArrayList<Address>) coder.getFromLocationName("Your Address", 50);
	          for(Address add : adresses){
	              if (statement) {//Controls to ensure it is right address such as country etc.
	                  double longitude = add.getLongitude();
	                  double latitude = add.getLatitude();
	              }
	          }
	      } catch (IOException e) {
	          e.printStackTrace();
	      }
		*/
	}
	
	private String getDirectionsUrl(LatLng origin,LatLng dest){
			
		String parameters = "";
		
		// 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
//origine		String parameters = str_origin+"&"+str_dest+"&"+sensor;


		if (DirectionMode == MODE_DRIVING) 
		{
			String mode = "&mode=driving";
			parameters = str_origin+"&"+str_dest+"&"+sensor+"&"+mode;
			
		} 
		else if (DirectionMode == MODE_WALKING)
		{
			String mode = "&mode=walking";
			parameters = str_origin+"&"+str_dest+"&"+sensor+"&"+mode;
		}
		
		
		// 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 parser = new DirectionsJSONParser();
            	
            	// 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<LatLng> points = null;
			PolylineOptions lineOptions = null;
			MarkerOptions markerOptions = new MarkerOptions();
			String distance = "";
			String duration = "";
			
			
			
			if(result.size()<1){
				Toast.makeText(getBaseContext(), "No Points", Toast.LENGTH_SHORT).show();
				return;
			}
				
			
			// Traversing through all the routes
			for(int i=0;i<result.size();i++){
				points = new ArrayList<LatLng>();
				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);	
					
					if(j==0){	// Get distance from the list
						distance = (String)point.get("distance");						
						continue;
					}else if(j==1){ // Get duration from the list
						duration = (String)point.get("duration");
						continue;
					}
					
					double lat = Double.parseDouble(point.get("lat"));
					double lng = Double.parseDouble(point.get("lng"));
					LatLng position = new LatLng(lat, lng);	
					
					points.add(position);						
				}
				
				// Adding all the points in the route to LineOptions
				lineOptions.addAll(points);
				lineOptions.width(2);
				lineOptions.color(Color.RED);	
				
			}
			
			tvDistanceDuration.setText("Distance:"+distance + ", Duration:"+duration);
			
			// Drawing polyline in the Google Map for the i-th route
			map.addPolyline(lineOptions);							
		}			
    }   
    
    
	
    private String getCompleteAddressString(double LATITUDE, double LONGITUDE) 
    {
        String strAdd = "";
        Geocoder geocoder = new Geocoder(this, Locale.getDefault());
        try {
            List<android.location.Address> addresses = geocoder.getFromLocation(LATITUDE, LONGITUDE, 1);
            if (addresses != null) {
                android.location.Address returnedAddress = addresses.get(0);
                StringBuilder strReturnedAddress = new StringBuilder("");

                for (int i = 0; i < returnedAddress.getMaxAddressLineIndex(); i++) {
                    strReturnedAddress.append(returnedAddress.getAddressLine(i)).append("\n");
                }
                strAdd = strReturnedAddress.toString();
                Log.w("My Current loction address", "" + strReturnedAddress.toString());
            } else {
                Log.w("My Current loction address", "No Address returned!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.w("My Current loction address", "Canont get Address!");
        }
        return strAdd;
    }
    
   
    
    public void  getLocationFromAddress(String strAddress) // LatLng  ou GeoPoint ???
    {

    	Geocoder coder = new Geocoder(this);
    	List<android.location.Address> address;
    	
    	//GeoPoint p1 = null;
    	// List<Address> addresses;
    	
    	try 
    	{
			address = coder.getFromLocationName(strAddress,5);
			
			if (address==null) 
			{
			      // return null;
				Toast.makeText(getBaseContext(), "Adresse introuvable !.", Toast.LENGTH_LONG).show();
			}
			else
			{	
			    android.location.Address location= address.get(0);
			    
			    
			    location.getLatitude();
			    location.getLongitude();

			    LatLng p1 = new LatLng(location.getLatitude(), location.getLongitude() );
			    
			   // p1 = new GeoPoint((double) (location.getLatitude() * 1E6),   (double) (location.getLongitude() * 1E6));
			}
		} 
    	catch (IOException e) 
    	{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

    	
    	    
    	}
    
	
	/*******************************************************************************************/

	@Override
	public boolean onCreateOptionsMenu(Menu menu) 
	{
			getMenuInflater().inflate(R.menu.activity_main, menu);
			return true;
	}
	
	@Override
    public boolean onOptionsItemSelected(MenuItem item) 
	{
       
		//googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
		//googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
		//googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
		//googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
		//googleMap.setMapType(GoogleMap.MAP_TYPE_NONE);
		
		Intent Intent;
		 
	        switch (item.getItemId())
	        {
	        
	        	case R.id.menu_geolocalisation:
	        		Intent = new Intent(MainActivity.this, Geolocalisation02.class);
	        		startActivity(Intent);
	        		return true;
	        
	        	case R.id.menu_compas:
	        		Intent = new Intent(MainActivity.this, Compas.class);
	        		startActivity(Intent);
	        		return true;	
	        
	        	case R.id.menu_direction:
	        		Intent = new Intent(MainActivity.this, Geo03.class);
	        		startActivity(Intent);
	        		return true;		
	        		
	        		
		        case R.id.menu_remind:
		  			Toast.makeText(getApplicationContext(),"Remind",Toast.LENGTH_SHORT).show();
		  			map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
		  			//Intent Intent04 = new Intent(MainActivity.this, NewActivity.class);
		  			//startActivity(Intent04);
			        return true;
		        
		  		case R.id.menu_repeat:
		  			Toast.makeText(getApplicationContext(),"Repeat",Toast.LENGTH_SHORT).show();
		  			
		  			map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
		  			//Intent Intent05 = new Intent(MainActivity.this, Control_Service.class);
		  			//startActivity(Intent05);
			        return true;
			        
		  		case R.id.menu_about:
		  			Toast.makeText(getApplicationContext(),"CAbout",Toast.LENGTH_SHORT).show();
		  			Intent Intent05 = new Intent(MainActivity.this, Geocoder_find_address.class);
		  			startActivity(Intent05);
		  			//map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
			        return true;
			        
		  		case R.id.menu_autocomplete:
		  		
		  			Intent Intent06 = new Intent(MainActivity.this, Geo04.class); // AutoComplete
		  			startActivity(Intent06);
		  			//map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
			        return true;    
			        
		  		case R.id.menu_pedometre:
		  			Intent = new Intent(MainActivity.this, Podometre_mode.class);
	        		startActivity(Intent);
		  			
		  			
		  			//Intent Intent07 = new Intent(MainActivity.this, podometre01.class); // AutoComplete
		  			//startActivity(Intent07);
		  			//map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
			        return true;        
		
		  		case R.id.menu_quit:
		  			Toast.makeText(getApplicationContext(),"Salut on ferme la boutique...",Toast.LENGTH_SHORT).show();
		  			finish();
			        return true;    
		          
		  		default:
		          return super.onOptionsItemSelected(item);
             }
    }
	
	/*******************************************************************************************/

	
}

class DirectionsJSONParser {
	
	/** 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;	
		JSONObject jDistance = null;
		JSONObject jDuration = 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<HashMap<String, String>> path = new ArrayList<HashMap<String, String>>();				
				
				/** Traversing all legs */
				for(int j=0;j<jLegs.length();j++){
					
					/** Getting distance from the json data */
					jDistance = ((JSONObject) jLegs.get(j)).getJSONObject("distance");
					HashMap<String, String> hmDistance = new HashMap<String, String>();
					hmDistance.put("distance", jDistance.getString("text"));
					
					/** Getting duration from the json data */
					jDuration = ((JSONObject) jLegs.get(j)).getJSONObject("duration");
					HashMap<String, String> hmDuration = new HashMap<String, String>();
					hmDuration.put("duration", jDuration.getString("text"));
					
					/** Adding distance object to the path */
					path.add(hmDistance);
					
					/** Adding duration object to the path */
					path.add(hmDuration);					
					
					
					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<LatLng> 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 : jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java 
	 * */
    private List<LatLng> decodePoly(String encoded) {

        List<LatLng> poly = new ArrayList<LatLng>();
        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;
    }
}


