package com.baidu.ai.sample.util;

import static android.content.Context.LOCATION_SERVICE;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

public class LocationClient {
    private static final String TAG = "LocationClient";
    private LocationManager locationManager;
    private static final int LOCATION_PERMISSION_REQUEST = 300;
    private LocationClient.Callback mCallback;
    private Activity mActivity;

    public LocationClient(Activity activity, LocationClient.Callback callback) {
        mActivity = activity;
        mCallback = callback;
        locationManager = (LocationManager) mActivity.getSystemService(LOCATION_SERVICE);
    }

    public void request(Context context) {
        if (hasLocationHardware(context)) {
            Log.i(TAG, "hardware  has FEATURE_LOCATION ");
            requestLocation();
        } else {
            Log.i(TAG, "hardware does not has FEATURE_LOCATION");
        }
    }

    public void destroy() {
        mActivity = null;
        mCallback = null;
    }

    public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == LOCATION_PERMISSION_REQUEST) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                requestLocation();
                return true;
            }
        }
        return false;
    }

    public boolean checkPermission() {
        if (ActivityCompat.checkSelfPermission(mActivity.getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(mActivity.getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST);
            return true;
        }
        return false;
    }
    public static boolean hasLocationHardware(Context context) {
        boolean gps = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
        boolean network = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_NETWORK);
        return gps && network;
    }

    private void requestLocation() {
        if (checkPermission()) {
            return;
        }

        try {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 10, locationListener);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    private final LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            double latitude = location.getLatitude();
            double longitude = location.getLongitude();
            Log.d(TAG, "Location -> Lat: " + latitude + ", Lng: " + longitude);
            getCityAndDistrict(latitude, longitude);
        }
    };

    private void getCityAndDistrict(double latitude, double longitude) {
        Geocoder geocoder = new Geocoder(mActivity.getApplicationContext(), Locale.getDefault());
        try {
            String cord = "" + latitude + "," + longitude;
            List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
            if (!addresses.isEmpty()) {
                String cityName = addresses.get(0).getLocality();
                String district = addresses.get(0).getSubLocality();

                Log.d(TAG, "Current City: " + cityName + ", district:" + district);
                if (mCallback != null) {
                    mCallback.onResult(0, addresses.get(0), cord);
                }
            } else {
                if (mCallback != null) {
                    mCallback.onResult(-1, null, cord);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public interface Callback {

        void onResult(int code, Address address, String cord);
    }
}
