package com.example.location;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.List;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class LocationActivity extends Activity {
    private Location currentLocation;
    private Location savedLocation;
    private LocationListener locationListener;
    private LocationManager locationManager;
    private PendingIntent proximityPendingIntent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.location_layout);

        locationManager = (LocationManager) 
                getSystemService(Context.LOCATION_SERVICE);

        locationListener = new LocationListener() {
            public void onLocationChanged(Location location) {
                if (location != null) {
                    currentLocation = location;
                    displayLocation();
                }
            }

            public void onStatusChanged(String provider, int status,
                    Bundle extras) {
            }

            public void onProviderEnabled(String provider) {
                String text = provider + " "
                        + getResources().getString(R.string.enabled);
                setStatusText(text);
            }

            public void onProviderDisabled(String provider) {
                String text = provider + " "
                        + getResources().getString(R.string.disabled);
                setStatusText(text);
            }
        };

        // Button Listeners
        Button savePoint = (Button) findViewById(R.id.buttonSavePoint);
        savePoint.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isCurrentLocationNull()) {
                    return;
                }

                savedLocation = currentLocation;
                setStatusText(getResources().
                        getString(R.string.locationSavedMessage));
            }
        });

        Button distanceToStart = 
                (Button) findViewById(R.id.buttonDistanceToStart);
        distanceToStart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isCurrentLocationNull() || savedLocation == null) {
                    return;
                }

                float totalMeters = 
                        savedLocation.distanceTo(currentLocation);
                setStatusText(getMetersFormattedString(totalMeters));

            }
        });

        Button bearingToStart = 
                (Button) findViewById(R.id.buttonBearingToStart);
        bearingToStart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isCurrentLocationNull() || savedLocation == null) {
                    return;
                }

                float bearing = 
                        savedLocation.bearingTo(currentLocation);
                setStatusText(getResources().getString(R.string.bearing)
                        + " " + bearing);
            }
        });

        Button address = (Button) findViewById(R.id.buttonAddress);
        address.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isCurrentLocationNull()) {
                    return;
                }

                if (Geocoder.isPresent()) {
                    final Geocoder geocoder = new Geocoder(
                            LocationActivity.this);
                    final Handler handler = new Handler();

                    Thread workerThread = new Thread(new Runnable() {
                        public void run() {
                            final StringBuffer address = reverseGeocode(
                                    geocoder, currentLocation);

                            handler.post(new Runnable() {
                                public void run() {
                                    Toast.makeText(
                                            LocationActivity.this,
                                            address, Toast.LENGTH_LONG)
                                            .show();
                                }
                            });
                        }
                    });
                    workerThread.start();
                }
            }
        });

        Button mapLocation = 
                (Button) findViewById(R.id.buttonMapLocation);
        mapLocation.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isCurrentLocationNull()) {
                    return;
                }

                Intent intent = new Intent(LocationActivity.this,
                        YouAreHereMapActivity.class);
                Bundle extras = new Bundle();
                extras.putDouble("latitude", 
                        currentLocation.getLatitude());
                extras.putDouble("longitude", 
                        currentLocation.getLongitude());
                if (savedLocation != null) {
                  extras.putDouble("savedLat", savedLocation.getLatitude());
                  extras.putDouble("savedLng", savedLocation.getLongitude());
                }
                intent.putExtras(extras);
                startActivity(intent);
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        locationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER,1000,0,locationListener);

        // add proximity alert
        double denverLatitude = 39.7392;
        double denverLongitude = -104.9850;
        int oneKMRadius = 1000;

        Intent i = 
                new Intent(this, ProximityAlertBroadcastReceiver.class);
        proximityPendingIntent = PendingIntent.getBroadcast(this, 0, i,
                PendingIntent.FLAG_UPDATE_CURRENT);

        locationManager.addProximityAlert(denverLatitude,
                denverLongitude, oneKMRadius, -1,
                proximityPendingIntent);
    }

    @Override
    public void onPause() {
        super.onPause();
        locationManager.removeUpdates(locationListener);
        // remove proximity alert
        locationManager.removeProximityAlert(proximityPendingIntent);
    }

    private StringBuffer reverseGeocode(Geocoder gc, Location loc) {
        StringBuffer addressSB = new StringBuffer();
        List<Address> addresses;
        try {
            addresses = gc.getFromLocation(loc.getLatitude(),
                    loc.getLongitude(), 1);

            if (addresses.size() == 1) {
                Address add = addresses.get(0);
                for (int i = 0; i < add.getMaxAddressLineIndex(); i++) {
                    addressSB.append(add.getAddressLine(i));
                    addressSB.append("\n");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return addressSB;
    }

    private String getMetersFormattedString(float meters) {
        String pattern = "###,###,##0.00";
        DecimalFormat myFormatter = new DecimalFormat(pattern);
        String metersString = myFormatter.format(meters);

        Resources resources = getResources();
        String text = resources.getString(R.string.distance) + " "
                + metersString + " "
                + resources.getString(R.string.meters);
        return text;
    }

    private boolean isCurrentLocationNull() {
        if (currentLocation == null) {
            Toast.makeText(LocationActivity.this, "No location",
                    Toast.LENGTH_LONG).show();
            return true;
        } 
        else {
            return false;
        }
    }

    private void displayLocation() {
        Resources resource = getResources();
        TextView tvLocation = 
                (TextView) findViewById(R.id.textViewLocation);
        tvLocation.setText(resource.getString(R.string.location)
                + " " + currentLocation.getLatitude()
                + ", " + currentLocation.getLongitude());
    }

    private void setStatusText(String status) {
        TextView tvStatus = 
                (TextView) findViewById(R.id.textViewStatus);
        tvStatus.setText(status);
    }
}
