package com.siwei.recyclebox.utils;

import android.util.Log;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.siwei.recyclebox.application.AppApplication;
import com.siwei.recyclebox.entity.MapLocationInfo;

/**
 * 定位帮助类
 */
public class LocationUtils {

    private AMapLocationClient client = null;
    private AMapLocationClientOption mOption, DIYoption;
    private Object objLock = new Object();

    public AMapLocationListener myListener = new MyLocationListener();
    private LocationListener mLocationListener;

    private static LocationUtils mInstance;

    public static LocationUtils getInstance() {
        if (mInstance == null) {
            mInstance = new LocationUtils();
        }
        return mInstance;
    }


    public void onCreate(LocationListener locationListener) {
        mLocationListener = locationListener;
        registerListener(myListener);   //注册监听函数
        setLocationOption(getDefaultLocationClientOption());
    }

    /***
     *
     */
    public LocationUtils() {
        synchronized (objLock) {
            if (client == null) {
                client = new AMapLocationClient(AppApplication.getInstance());
                client.setLocationOption(getDefaultLocationClientOption());
            }
        }
    }

    /***
     * @param listener
     * @return
     */

    public boolean registerListener(AMapLocationListener listener) {
        boolean isSuccess = false;
        if (listener != null) {
            client.setLocationListener(listener);
            isSuccess = true;
        }
        return isSuccess;
    }

    public void unregisterListener(AMapLocationListener listener) {
        if (listener != null) {
            client.unRegisterLocationListener(listener);
        }
    }

    /***
     * @param option
     * @return isSuccessSetOption
     */
    public boolean setLocationOption(AMapLocationClientOption option) {
        boolean isSuccess = false;
        Log.i("locationFail", option.toString());
        if (option != null) {
            if (client.isStarted())
                client.stopLocation();
            DIYoption = option;
            client.setLocationOption(option);
            isSuccess = true;
        }
        return isSuccess;
    }

    public AMapLocationClientOption getOption() {
        return DIYoption;
    }

    /***
     * @return DefaultLocationClientOption
     */
    public AMapLocationClientOption getDefaultLocationClientOption() {

        if (mOption == null) {
            mOption = new AMapLocationClientOption();
//            mOption.setLocationMode(LocationMode.Hight_Accuracy);//可选，默认高精度，设置定位模式，高精度，低功耗，仅设备
//            mOption.setCoorType("bd09ll");//可选，默认gcj02，设置返回的定位结果坐标系，如果配合百度地图使用，建议设置为bd09ll;
//            mOption.setScanSpan(1000);//可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
//            mOption.setIsNeedAddress(true);//可选，设置是否需要地址信息，默认不需要
//            mOption.setOpenGps(true);// 可选，默认false,设置是否使用gps
//            mOption.setIsNeedLocationDescribe(false);//可选，设置是否需要地址描述
//            mOption.setNeedDeviceDirect(false);//可选，设置是否需要设备方向结果
//            mOption.setLocationNotify(false);//可选，默认false，设置是否当gps有效时按照1S1次频率输出GPS结果
//            mOption.setIgnoreKillProcess(false);//可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
//            mOption.setIsNeedLocationDescribe(false);//可选，默认false，设置是否需要位置语义化结果，可以在BDLocation.getLocationDescribe里得到，结果类似于“在北京天安门附近”
//            mOption.setIsNeedLocationPoiList(false);//可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
//            mOption.SetIgnoreCacheException(true);//可选，默认false，设置是否收集CRASH信息，默认收集

            int span = 1000;
            mOption.setInterval(span);// 可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
            mOption.setNeedAddress(true);// 可选，设置是否需要地址信息，默认不需要
            mOption.setLocationCacheEnable(false);
            //mOption.setOpenGps(true);// 可选，默认false,设置是否使用gps
            //mOption.setLocationNotify(true);// 可选，默认false，设置是否当gps有效时按照1S1次频率输出GPS结果
            //mOption.setIsNeedLocationDescribe(true);// 可选，默认false，设置是否需要位置语义化结果，可以在BDLocation.getLocationDescribe里得到，结果类似于“在北京天安门附近”
            //mOption.setIsNeedLocationPoiList(true);// 可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
            //mOption.setIgnoreKillProcess(false);// 可选，默认false，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认杀死
            //mOption.SetIgnoreCacheException(false);// 可选，默认false，设置是否收集CRASH信息，默认收集
            //mOption.setEnableSimulateGps(false);// 可选，默认false，设置是否需要过滤gps仿真结果，默认需要

//            mOption.setIsNeedAltitude(false);//可选，默认false，设置定位时是否需要海拔信息，默认不需要，除基础定位版本都可用
        }
        Log.i("locationFail", mOption.toString());
        return mOption;
    }

    public void start() {
        synchronized (objLock) {
            if (client != null) {
                client.startLocation();
            }
        }
    }

    public void stop() {
        synchronized (objLock) {
            if (client != null) {
                client.stopLocation();
            }
        }
    }

    /**
     * 设置定位相关参数
     */
//    private void setLocationOption() {
//        if (mOption != null) return;
//        mOption = new LocationClientOption();
//        mOption.setLocationMode(LocationMode.Hight_Accuracy);//设置定位模式
//        mOption.setCoorType("bd09ll");//返回的定位结果是百度经纬度，默认值gcj02
//        mOption.setScanSpan(5000);//设置发起定位请求的间隔时间为5000ms
//        mOption.setIsNeedAddress(true);//可选，设置是否需要地址信息，默认不需要
////        option.setIsNeedLocationDescribe(true);//可选，设置是否需要地址描述
////        option.setNeedDeviceDirect(false);//可选，设置是否需要设备方向结果
//        mOption.setLocationNotify(true);//可选，默认false，设置是否当gps有效时按照1S1次频率输出GPS结果
////        option.setEnableSimulateGps(false);//可选，默认false，设置是否需要过滤gps仿真结果，默认需要
//        mOption.setIgnoreKillProcess(true);//可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
//        mOption.setOpenGps(true);
//        mOption.setIsNeedLocationPoiList(false);//可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
//        mOption.SetIgnoreCacheException(true);//可选，默认false，设置是否收集CRASH信息，默认收集
//        mLocationClient.setLocOption(mOption);
//
//    }


    /**
     * 发起定位
     */
    public void startLocationInfo() {
        start();
    }

    /**
     * 停止定位
     */
    public void stopLocationClient() {
        unregisterListener(myListener); //注销掉监听
        stop(); //停止定位服务
    }


    /**
     * 定位监听
     * 百度地图
     * 61 ： GPS定位结果，GPS定位成功。
     * 62 ： 无法获取有效定位依据，定位失败，请检查运营商网络或者WiFi网络是否正常开启，尝试重新请求定位。
     * 63 ： 网络异常，没有成功向服务器发起请求，请确认当前测试手机网络是否通畅，尝试重新请求定位。
     * 65 ： 定位缓存的结果。
     * 66 ： 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果。
     * 67 ： 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果。
     * 68 ： 网络连接失败时，查找本地离线定位时对应的返回结果。
     * 161： 网络定位结果，网络定位成功。
     * 162： 请求串密文解析失败，一般是由于客户端SO文件加载失败造成，请严格参照开发指南或demo开发，放入对应SO文件。
     * 167： 服务端定位失败，请您检查是否禁用获取位置信息权限，尝试重新请求定位。
     * 502： AK参数错误，请按照说明文档重新申请AK。
     * 505：AK不存在或者非法，请按照说明文档重新申请AK。
     * 601： AK服务被开发者自己禁用，请按照说明文档重新申请AK。
     * 602： key mcode不匹配，您的AK配置过程中安全码设置有问题，请确保：SHA1正确，“;”分号是英文状态；且包名是您当前运行应用的包名，请按照说明文档重新申请AK。
     * 501～700：AK验证失败，请按照说明文档重新申请AK。
     * 高德地图
     * 6: LOCATION_TYPE_CELL 定位结果类型：基站定位结果 属于网络定位
     * 3: LOCATION_TYPE_FAST 已过时。 已合并到AMapLocation.LOCATION_TYPE_SAME_REQ
     * 4: LOCATION_TYPE_FIX_CACHE 定位结果类型：缓存定位结果 返回一段时间前设备在相同的环境中缓存下来的网络定位结果，节省无必要的设备定位消耗
     * 1: LOCATION_TYPE_GPS 定位结果类型：GPS定位结果 通过设备GPS定位模块返回的定位结果
     * 8: LOCATION_TYPE_OFFLINE 定位结果类型： 离线定位结果
     * 2: LOCATION_TYPE_SAME_REQ 定位结果类型：前次定位结果 网络定位请求低于1秒、或两次定位之间设备位置变化非常小时返回，设备位移通过传感器感知
     * 5: LOCATION_TYPE_WIFI 定位结果类型：Wifi定位结果 属于网络定位，定位精度相对基站定位会更好
     *
     * @author Administrator
     */
    public class MyLocationListener implements AMapLocationListener {
        @Override
        public void onLocationChanged(AMapLocation location) {
            MapLocationInfo mapLocationInfo = null;
            String message = "定位失败，请检查网络后重试！";
            Log.i("location000", location.toString());
            if (null != location) {
                message = location.getLocationType() + ":" + message;
                String address = location.getCity() + location.getDistrict() + location.getStreet() + location.getStreetNum() + location.getAoiName();
                if (location.getLocationType() == AMapLocation.LOCATION_TYPE_GPS) {// GPS定位结果
                    //gps定位成功
                    mapLocationInfo = new MapLocationInfo(address, location.getProvince(),
                            location.getCity(), location.getDistrict(), location.getStreet(), location.getLatitude(), location.getLongitude(), location.getAoiName(), location.getPoiName());
                } else if (location.getLocationType() == AMapLocation.LOCATION_TYPE_CELL || location.getLocationType() == AMapLocation.LOCATION_TYPE_WIFI) {// 网络定位结果
                    //网络定位成功
                    mapLocationInfo = new MapLocationInfo(address, location.getProvince(),
                            location.getCity(), location.getDistrict(), location.getStreet(), location.getLatitude(), location.getLongitude(), location.getAoiName(), location.getPoiName());
                } else if (location.getLocationType() == AMapLocation.LOCATION_TYPE_OFFLINE) {// 离线定位结果
                    //离线定位成功，离线定位结果也是有效的
                    mapLocationInfo = new MapLocationInfo(address, location.getProvince(),
                            location.getCity(), location.getDistrict(), location.getStreet(), location.getLatitude(), location.getLongitude(), location.getAoiName(), location.getPoiName());
                }
                stop();
//                else if (location.getLocType() == BDLocation.TypeServerError) {
                //服务端网络定位失败，可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com，会有人追查原因
//                } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                //网络不同导致定位失败，请检查查网络是否流畅
//                } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                // 无法获取有效定位依据导致定位失败，一般是由于手机的原因，处于飞行模式下一般会造成这种结果，可以试下重启手机
//                }
            }
            if (mLocationListener == null) return;
            if (mapLocationInfo != null) {
                mLocationListener.locationSuccess(mapLocationInfo, message);
            } else {
                mLocationListener.locationFail(message);
            }
        }
    }

    //定位监听
    public interface LocationListener {
        //定位成功
        void locationSuccess(MapLocationInfo mapLocationInfo, String locationType);

        //定位失败
        void locationFail(String message);
    }
}