package com.nsgk.ruralWeb.location;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

public class NSSystemLocation
{
    private static final String ID_TAG = NSSystemLocation.class.getName();
    public static final String FUSED_PROVIDER = "fused";

    private final Context        m_context;
    private       NSLocationInfo m_lastLocation = null;

    public NSSystemLocation(Context context)
    {
        m_context = context;
    }

    public NSLocationInfo GetLocation(String provider)
    {
        NSLocationInfo loc;

        try
        {
            loc = GetHighLocation(provider);
            if(null == loc)
                loc = GetLastLocation(provider);

            if(null != loc)
                m_lastLocation = loc;
            else
                ShowToast("定位失败, 请先开启位置服务", Toast.LENGTH_LONG);

            return loc;
        }
        catch(Throwable e)
        {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @SuppressLint("MissingPermission")
    private NSLocationInfo GetLastLocation(final String type)
    {
        NSLocationInfo loc = null;
        try
        {
            LocationManager lm = (LocationManager) m_context.getSystemService(Context.LOCATION_SERVICE);

            List<String> allProviders = lm.getAllProviders();
            Log.i(ID_TAG, "使用最近所有定位提供器: " + allProviders);
            Map<String, NSLocationInfo> map = new HashMap<>();
            for(String provider : allProviders)
            {
                Location lastKnownLocation = lm.getLastKnownLocation(provider);
                if(null == lastKnownLocation)
                    continue;
                NSLocationInfo l = new NSLocationInfo(provider, lastKnownLocation.getLongitude(), lastKnownLocation.getLatitude());
                map.put(provider, l);
            }

            Log.i(ID_TAG, "最近定位提供器结果: " + map);
            if(null != type && !type.isEmpty() && map.containsKey(type))
                loc = map.get(type);
            else if(map.containsKey(LocationManager.GPS_PROVIDER))
                loc = map.get(LocationManager.GPS_PROVIDER);
            else if(map.containsKey(LocationManager.NETWORK_PROVIDER))
                loc = map.get(LocationManager.NETWORK_PROVIDER);
            else if(map.containsKey(FUSED_PROVIDER))
                loc = map.get(FUSED_PROVIDER);
            else if(map.containsKey(LocationManager.PASSIVE_PROVIDER))
                loc = map.get(LocationManager.PASSIVE_PROVIDER);
            if(null == loc)
                Log.i(ID_TAG, "所有提供器无最近定位");
            else
                Log.i(ID_TAG, "使用提供器最近定位: " + loc.provider);
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
        return loc;
    }

    @SuppressLint("MissingPermission")
    private NSLocationInfo GetHighLocation(String provider)
    {
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
        {
            return null;
        }

        NSLocationInfo loc = null;
        try
        {
            LocationManager lm = (LocationManager) m_context.getSystemService(Context.LOCATION_SERVICE);
            if(null != provider)
            {
                if(LocationManager.GPS_PROVIDER.equals(provider))
                {
                    if(!lm.isProviderEnabled(provider))
                    {
                        Log.w(ID_TAG, "GPS定位提供器未启用, 尝试网络定位器");
                        provider = LocationManager.NETWORK_PROVIDER;
                        if(!lm.isProviderEnabled(provider))
                        {
                            Log.w(ID_TAG, "网络定位提供器也未启用");
                            provider = null;
                        }
                    }
                }
                else if(LocationManager.NETWORK_PROVIDER.equals(provider))
                {
                    Log.w(ID_TAG, "网络定位提供器未启用, 尝试GPS定位器");
                    if(!lm.isProviderEnabled(provider))
                    {
                        provider = LocationManager.GPS_PROVIDER;
                        if(!lm.isProviderEnabled(provider))
                        {
                            Log.w(ID_TAG, "GPS定位提供器也未启用");
                            provider = null;
                        }
                    }
                }
            }

            if(null == provider)
            {
                Criteria criteria = new Criteria();
                criteria.setAccuracy(Criteria.ACCURACY_FINE); // 高精度
//            criteria.setPowerRequirement(Criteria.POWER_HIGH);
//            criteria.setAltitudeRequired(false);
                provider = lm.getBestProvider(criteria, true);
            }
            Log.i(ID_TAG, "使用高精度定位提供器: " + provider);

            if(null == provider)
            {
                Log.i(ID_TAG, "无法获取高精度定位提供器");
                return null;
            }

            CompletableFuture<Location> future = new CompletableFuture<>();
            lm.getCurrentLocation(provider, null, m_context.getMainExecutor(), future::complete);
            Location location = future.get();
            if(null == location)
            {
                Log.i(ID_TAG, "无法使用高精度提供器定位");
                return null;
            }
            loc = new NSLocationInfo(provider, location.getLongitude(), location.getLatitude());
            Log.i(ID_TAG, "使用高精度提供器获取定位: " + loc);
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
        return loc;
    }

    private void ShowToast(final String message, int duration)
    {
        ((Activity)m_context).runOnUiThread((new Runnable() {
            @Override
            public void run()
            {
                Toast.makeText(m_context, message, duration).show();
            }
        }));
    }

    public NSLocationInfo GetLastLocation()
    {
        return m_lastLocation;
    }
}