package it.unipr.mobdev;

import it.unipr.mobdev.R;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements LocationListener{

	public static String TAG = "LocationExample";
	private LocationManager locationManager = null;
	private Location currentLocation = null;
	private TextView locationTextView = null;
	
	private static final int TWO_MINUTES = 1000 * 60 * 2;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Log.d(TAG,"onCreate()");

		locationTextView  = (TextView)findViewById(R.id.locationLabel);
		
		// Acquire a reference to the system Location Manager
		locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

		if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
		{
			Log.d(TAG,"GPS_PROVIDER is ebabled !");
			
			Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
			
			Log.d(TAG,"Last Known Location: " + lastKnownLocation);
			
			if(lastKnownLocation != null)
			{
				currentLocation = lastKnownLocation;
				locationTextView.setText("Provider: " + currentLocation.getProvider() + " Lat: " + currentLocation.getLatitude() + " Lng: " + currentLocation.getLongitude() + " Accuracy: " + currentLocation.getAccuracy());
			}

			locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
		}
		else
			Toast.makeText(this, "GPS is not ebabled !", Toast.LENGTH_LONG).show();
		
		if(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
		{
			Log.d(TAG,"NETWORK_PROVIDER is ebabled !");
			
			Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
			
			Log.d(TAG,"Last Known Location: " + lastKnownLocation);
			
			if(lastKnownLocation != null && isBetterLocation(lastKnownLocation,currentLocation))
			{
				currentLocation = lastKnownLocation;
				locationTextView.setText("Provider: " + currentLocation.getProvider() + " Lat: " + currentLocation.getLatitude() + " Lng: " + currentLocation.getLongitude() + " Accuracy: " + currentLocation.getAccuracy());
			}

			// Register the listener with the Location Manager to receive location updates
			locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
		}
		else
			Toast.makeText(this, "LOCATION NETWORK PROVIDER is not ebabled !", Toast.LENGTH_LONG).show();
	}


	@Override
	protected void onDestroy() {
		Log.d(TAG,"onDestroy()");
		super.onDestroy();
		if(locationManager != null)
			locationManager.removeUpdates(this);
	}


	@Override
	public void onLocationChanged(Location location) {
		Log.d(TAG,"onLocationChanged(): Provider: " + location.getProvider() + " Lat: " + location.getLatitude() + " Lng: " + location.getLongitude() + " Accuracy: " + location.getAccuracy());
		
		if(currentLocation == null)				
			currentLocation = location;
		else
			if(isBetterLocation(location, currentLocation))
			{
				Log.d(TAG,"onLocationChanged(): Updating Location ... ");
				currentLocation = location;
				locationTextView.setText("Provider: " + currentLocation.getProvider() + " Lat: " + currentLocation.getLatitude() + " Lng: " + currentLocation.getLongitude() + " Accuracy: " + currentLocation.getAccuracy());
			}
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		Log.d(TAG,"onStatusChanged()");
	}

	@Override
	public void onProviderEnabled(String provider) {
		Log.d(TAG,"onProviderEnabled()");
	}

	@Override
	public void onProviderDisabled(String provider) {
		Log.d(TAG,"onProviderDisabled()");
	}

	/** Determines whether one Location reading is better than the current Location fix
	 * @param location  The new Location that you want to evaluate
	 * @param currentBestLocation  The current Location fix, to which you want to compare the new one
	 */
	protected boolean isBetterLocation(Location location, Location currentBestLocation) {
		if (currentBestLocation == null) {
			// A new location is always better than no location
			return true;
		}

		// Check whether the new location fix is newer or older
		long timeDelta = location.getTime() - currentBestLocation.getTime();
		boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
		boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
		boolean isNewer = timeDelta > 0;

		// If it's been more than two minutes since the current location, use the new location
		// because the user has likely moved
		if (isSignificantlyNewer) {
			return true;
			// If the new location is more than two minutes older, it must be worse
		} else if (isSignificantlyOlder) {
			return false;
		}

		// Check whether the new location fix is more or less accurate
		int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
		boolean isLessAccurate = accuracyDelta > 0;
		boolean isMoreAccurate = accuracyDelta < 0;
		boolean isSignificantlyLessAccurate = accuracyDelta > 200;

		// Check if the old and new location are from the same provider
		boolean isFromSameProvider = isSameProvider(location.getProvider(),
				currentBestLocation.getProvider());

		// Determine location quality using a combination of timeliness and accuracy
		if (isMoreAccurate) {
			return true;
		} else if (isNewer && !isLessAccurate) {
			return true;
		} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
			return true;
		}
		return false;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
		if (provider1 == null) {
			return provider2 == null;
		}
		return provider1.equals(provider2);
	}
}