package com.tofly.ghrq_route.module.gps;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import androidx.annotation.RequiresApi;

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.amap.api.location.AMapLocationQualityReport;
import com.mgq.base.utils.logger.LogRecorder;
import com.tofly.ghrq_route.R;
import com.tofly.ghrq_route.base.BaseApp;
import com.tofly.ghrq_route.base.C;
import com.tofly.ghrq_route.module.gps.domain.GPSDataBean;
import com.tofly.ghrq_route.module.service.AlarmReceiver;
import com.tofly.ghrq_route.module.user.domain.UserBean;
import com.tofly.ghrq_route.common.ui.activity.HomeActivity;
import com.tofly.ghrq_route.common.util.AlarmUtils.AlarmUtils;
import com.tofly.ghrq_route.common.util.Location.LocationUtil_xu;
import com.tofly.ghrq_route.common.util.date.DateUtils;

/**
 * Created by Amu on 2018/3/25.
 */

public class AmapLocationUtils {

    private static AmapLocationUtils amapLocUtil = null;

    private Intent foreService;

    private DService myService;

    private AMapLocationClient locationClient = null;

    private AMapLocationClientOption locationOption = null;

    private GpsTool gpsTool;

    private AlarmReceiver alarmReceiver;

    private boolean mbRegisterScreenOn = false;

    private boolean mbKeepScreenWakeup = false;

    public static final int REQCODE_AMAP_WAKEUP = 300;

    public static final String ACTION_AMAP_WAKEUP = "com.route.AmapLocationUtils.wakeup";

    private static int mCheckGPSOpenTimes = 0;

    private String mLastUpdateStatusTime = null;

    private boolean isRunning = false;

    private boolean isOnceLocation = false;

    private NotificationManager notificationManager;

    boolean isCreateChannel = false;

    public static synchronized AmapLocationUtils getInstance() {
        if (amapLocUtil == null) {
            amapLocUtil = new AmapLocationUtils();
        }
        return amapLocUtil;
    }

    //构建前台service
    private static final String NOTIFICATION_CHANNEL_NAME = "BackgroundLocation";
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    private Notification constructNotification() {
        // 在API11之后构建Notification的方式
        Context appContext = BaseApp.getInstance().getApplicationContext();
        if (null == notificationManager) {
            notificationManager = (NotificationManager) BaseApp.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
        }
        Notification.Builder builder; //获取一个Notification构造器
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String channelId = appContext.getPackageName();
            if (!isCreateChannel) {
                NotificationChannel channel = new NotificationChannel(
                        channelId,
                        NOTIFICATION_CHANNEL_NAME,
                        NotificationManager.IMPORTANCE_DEFAULT
                );
                notificationManager.createNotificationChannel(channel);
                isCreateChannel = true;
            }
            builder = new Notification.Builder(appContext, channelId);
        }else {
            builder = new Notification.Builder(appContext);
        }

        Intent nfIntent = new Intent(appContext, HomeActivity.class);
        builder.setContentIntent(PendingIntent.getActivity(appContext, 0, nfIntent, 0))
                .setContentTitle("上传高德GPS") // 设置下拉列表里的标题
                .setContentText("巡检系统")// 设置上下文内容
                .setSmallIcon(R.mipmap.logo)
                .setWhen(System.currentTimeMillis());

        Notification notification = builder.build();// 获取构建好的Notification
        notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
        notification.flags = Notification.FLAG_ONGOING_EVENT;
        notification.flags |= Notification.FLAG_NO_CLEAR;
        notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;

        // 参数一：唯一的通知标识；参数二：通知消息。
        return notification;
    }

    /**
     * 初始化定位
     *
     * @since 2.8.0
     * @author hongming.wang
     *
     */
    private void initLocation(){
        Context appContext = BaseApp.getInstance().getApplicationContext();
        //初始化client
        locationClient = new AMapLocationClient(appContext);
        locationOption = getDefaultOption();
        //设置定位参数
        locationClient.setLocationOption(locationOption);
        // 设置定位监听
        locationClient.setLocationListener(locationListener);
    }

    private void initOnceLocation(){
        Context appContext = BaseApp.getInstance().getApplicationContext();
        //初始化client
        locationClient = new AMapLocationClient(appContext);
        locationOption = getDefaultOption();
        locationOption.setOnceLocationLatest(true);
        locationOption.setOnceLocation(true);
        //设置定位参数
        locationClient.setLocationOption(locationOption);
        // 设置定位监听
        locationClient.setLocationListener(locationListener);
    }

    /**
     * 默认的定位参数
     * @since 2.8.0
     * @author hongming.wang
     *
     */
    public AMapLocationClientOption getDefaultOption(){
        AMapLocationClientOption mOption = new AMapLocationClientOption();
        mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选，设置定位模式，可选的模式有高精度、仅设备、仅网络。默认为高精度模式
        mOption.setGpsFirst(false);//可选，设置是否gps优先，只在高精度模式下有效。默认关闭
        mOption.setHttpTimeOut(30000);//可选，设置网络请求超时时间。默认为30秒。在仅设备模式下无效
        mOption.setInterval(2000);//可选，设置定位间隔。默认为2秒
        mOption.setNeedAddress(true);//可选，设置是否返回逆地理地址信息。默认是true
        mOption.setOnceLocation(false);//可选，设置是否单次定位。默认是false
        mOption.setOnceLocationLatest(false);//可选，设置是否等待wifi刷新，默认为false.如果设置为true,会自动变为单次定位，持续定位时不要使用
        AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选， 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
        mOption.setSensorEnable(false);//可选，设置是否使用传感器。默认是false
        mOption.setWifiScan(true); //可选，设置是否开启wifi扫描。默认为true，如果设置为false会同时停止主动刷新，停止以后完全依赖于系统刷新，定位位置可能存在误差
        mOption.setLocationCacheEnable(true); //可选，设置是否使用缓存定位，默认为true
        return mOption;
    }

    /**
     * 定位监听
     */
    AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation location) {
            if (null != location) {
                if (location.getErrorCode() == 0) {
                    //上传.
                    String userid = "";
                    UserBean userBean = BaseApp.getInstance().getLoginUser();
                    if (userBean != null)
                        userid = userBean.getUserid();
                    Context context = BaseApp.getInstance().getApplicationContext();
                    if (C.bLogMapToolLocForBaiduArcgis_debug) {
                        /*高德gcj02坐标转换为wgs84坐标*/
                        LocationUtil_xu.CoordinateClass coordinate = LocationUtil_xu.gcj02towgs84(location.getLongitude(), location.getLatitude());
                        if (coordinate != null){
                            String lng = String.format("%.6f", coordinate.Longtitude);
                            String lat = String.format("%.6f", coordinate.Latitude);
                            String check_time = DateUtils.getDateTimeMS();
                            String gps_time = DateUtils.getDateTimeMS(location.getTime());
                            String provider = String.valueOf(location.getLocationType());
                            String accuracy = String.format("%.2f", location.getAccuracy());
                            String gps_star = String.valueOf(location.getSatellites());
                            String logMsg = String.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
                                    check_time, gps_time, lng, lat, provider, accuracy, gps_star);
                            LogRecorder.writeAmapLog(context, logMsg, userid);
                        }

                        if (userBean != null){
                            uploadGps(location);
                        }
                    }
                }

                /*StringBuffer sb = new StringBuffer();
                //errCode等于0代表定位成功，其他的为定位失败，具体的可以参照官网定位错误码说明
                if(location.getErrorCode() == 0){
                    sb.append("定位成功" + "\n");
                    sb.append("定位类型: " + location.getLocationType() + "\n");
                    sb.append("经    度    : " + location.getLongitude() + "\n");
                    sb.append("纬    度    : " + location.getLatitude() + "\n");
                    sb.append("精    度    : " + location.getAccuracy() + "米" + "\n");
                    sb.append("提供者    : " + location.getProvider() + "\n");

                    sb.append("速    度    : " + location.getSpeed() + "米/秒" + "\n");
                    sb.append("角    度    : " + location.getBearing() + "\n");
                    // 获取当前提供定位服务的卫星个数
                    sb.append("星    数    : " + location.getSatellites() + "\n");
                    sb.append("国    家    : " + location.getCountry() + "\n");
                    sb.append("省            : " + location.getProvince() + "\n");
                    sb.append("市            : " + location.getCity() + "\n");
                    sb.append("城市编码 : " + location.getCityCode() + "\n");
                    sb.append("区            : " + location.getDistrict() + "\n");
                    sb.append("区域 码   : " + location.getAdCode() + "\n");
                    sb.append("地    址    : " + location.getAddress() + "\n");
                    sb.append("兴趣点    : " + location.getPoiName() + "\n");
                    //定位完成的时间
                    sb.append("定位时间: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
                } else {
                    //定位失败
                    sb.append("定位失败" + "\n");
                    sb.append("错误码:" + location.getErrorCode() + "\n");
                    sb.append("错误信息:" + location.getErrorInfo() + "\n");
                    sb.append("错误描述:" + location.getLocationDetail() + "\n");
                }
                sb.append("***定位质量报告***").append("\n");
                sb.append("* WIFI开关：").append(location.getLocationQualityReport().isWifiAble() ? "开启":"关闭").append("\n");
                sb.append("* GPS状态：").append(getGPSStatusString(location.getLocationQualityReport().getGPSStatus())).append("\n");
                sb.append("* GPS星数：").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
                sb.append("****************").append("\n");
                //定位之后的回调时间
                sb.append("回调时间: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");*/

            }
            mCheckGPSOpenTimes++;
            if (mCheckGPSOpenTimes >= 10){
                checkGpsSettingOpen();
                mCheckGPSOpenTimes = 0;
            }
        }

        private void uploadGps(AMapLocation aMapLocation){
            UserBean userBean = BaseApp.getInstance().getLoginUser();
            if (userBean != null && aMapLocation != null
                    && aMapLocation.getLongitude() > 0 && aMapLocation.getLatitude() > 0) {
                GPSDataBean gpsDataBean = GPSDataBean.GpsDataFromAMapLocation(userBean, aMapLocation);
                if (gpsTool == null)
                    gpsTool = GpsTool.getInstance();

                if (!isOnceLocation) {
                    String gps_time = DateUtils.getDateTimeMS(aMapLocation.getTime());
                    gpsTool.checkGpsDataAndUpload(userBean, gpsDataBean, gps_time, true);

                    /*更新gpsStatus->移动监控模块*/
                    checkNeedUdateGpsStatus(gpsDataBean);
                }else {
                    gpsTool.updateGPSStatus(gpsDataBean);
                }
            }
        }
    };

    /*超过设定的时间则上传GPS状态信息*/
    private void checkNeedUdateGpsStatus(GPSDataBean gpsData) {
        int period = BaseApp.getInstance().getGpsSatusTime();
        String now_time = DateUtils.getDate();
        boolean isPast;
        if (mLastUpdateStatusTime == null || mLastUpdateStatusTime.isEmpty()) {
            isPast = true;
        }else {
            long timeOffset = DateUtils.getTimeOffset(now_time, mLastUpdateStatusTime);
            isPast = timeOffset >= period;
        }

        if (isPast) {
            mLastUpdateStatusTime = now_time;
            gpsTool.updateGPSStatus(gpsData);
        }
    }

    /**
     * 获取GPS状态的字符串
     * @param statusCode GPS状态码
     * @return
     */
    private String getGPSStatusString(int statusCode){
        String str = "";
        switch (statusCode){
            case AMapLocationQualityReport.GPS_STATUS_OK:
                str = "GPS状态正常";
                break;
            case AMapLocationQualityReport.GPS_STATUS_NOGPSPROVIDER:
                str = "手机中没有GPS Provider，无法进行GPS定位";
                break;
            case AMapLocationQualityReport.GPS_STATUS_OFF:
                str = "GPS关闭，建议开启GPS，提高定位质量";
                break;
            case AMapLocationQualityReport.GPS_STATUS_MODE_SAVING:
                str = "选择的定位模式中不包含GPS定位，建议选择包含GPS定位的模式，提高定位质量";
                break;
            case AMapLocationQualityReport.GPS_STATUS_NOGPSPERMISSION:
                str = "没有GPS定位权限，建议开启gps定位权限";
                break;
        }
        return str;
    }
    // 根据控件的选择，重新设置定位参数
    private void resetOption() {
        int period = 1000/*BaseApp.getInstance().getGpsWakeTime()*/;
        locationOption.setNeedAddress(false);
        locationOption.setLocationCacheEnable(true);
        locationOption.setInterval(period);
        /*// 设置是否需要显示地址信息
        locationOption.setNeedAddress(cbAddress.isChecked());
        *//**
         * 设置是否优先返回GPS定位结果，如果30秒内GPS没有返回定位结果则进行网络定位
         * 注意：只有在高精度模式下的单次定位有效，其他方式无效
         *//*
        locationOption.setGpsFirst(cbGpsFirst.isChecked());
        // 设置是否开启缓存
        locationOption.setLocationCacheEnable(cbCacheAble.isChecked());
        // 设置是否单次定位
        locationOption.setOnceLocation(cbOnceLocation.isChecked());
        //设置是否等待设备wifi刷新，如果设置为true,会自动变为单次定位，持续定位时不要使用
        locationOption.setOnceLocationLatest(cbOnceLastest.isChecked());
        //设置是否使用传感器
        locationOption.setSensorEnable(cbSensorAble.isChecked());
        //设置是否开启wifi扫描，如果设置为false时同时会停止主动刷新，停止以后完全依赖于系统刷新，定位位置可能存在误差
        String strInterval = etInterval.getText().toString();
        if (!TextUtils.isEmpty(strInterval)) {
            try{
                // 设置发送定位请求的时间间隔,最小值为1000，如果小于1000，按照1000算
                locationOption.setInterval(Long.valueOf(strInterval));
            }catch(Throwable e){
                e.printStackTrace();
            }
        }

        String strTimeout = etHttpTimeout.getText().toString();
        if(!TextUtils.isEmpty(strTimeout)){
            try{
                // 设置网络请求超时时间
                locationOption.setHttpTimeOut(Long.valueOf(strTimeout));
            }catch(Throwable e){
                e.printStackTrace();
            }
        }*/
    }

    /**
     * 开始定位
     *
     * @since 2.8.0
     * @author hongming.wang
     *
     */
    private void startLocation(){
        //根据控件的选择，重新设置定位参数
        resetOption();
        // 设置定位参数
        locationClient.setLocationOption(locationOption);
        // 启动定位
        locationClient.startLocation();
        //启动后台定位
        locationClient.enableBackgroundLocation(2001, constructNotification());

        GpsTool.getInstance().resetUploadGpsTimes();

        mCheckGPSOpenTimes = 0;
       checkGpsSettingOpen();
    }

    private void startLocationOnce() {
        // 启动定位
        locationClient.startLocation();

        mCheckGPSOpenTimes = 0;
        checkGpsSettingOpen();
    }

    private void checkGpsSettingOpen(){
        if (gpsTool == null)
            gpsTool = GpsTool.getInstance();
       gpsTool.checkGpsSettingOpen();
    }

    public boolean isServiceRunning() {
        return isRunning;
    }

    /**
     * 停止定位
     *
     * @since 2.8.0
     * @author hongming.wang
     *
     */
    private void stopLocation(){
        // 停止定位
        if (null != locationClient) {
            locationClient.stopLocation();
        }
    }

    /**
     * 销毁定位
     *
     * @since 2.8.0
     * @author hongming.wang
     *
     */
    private void destroyLocation(){
        if (null != locationClient) {
            /**
             * 如果AMapLocationClient是在当前Activity实例化的，
             * 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
             */
            locationClient.onDestroy();
            locationClient = null;
            locationOption = null;
        }
    }

    public void startAmapLocService(){
        isOnceLocation = false;

        //初始化定位
        initLocation();
        //开始定位
        startLocation();
        //屏幕常亮
        setScreenKeepOn();

        isRunning = true;
    }

    //开启单次定位
    public void startAmapLocServiceForOnce() {
        isOnceLocation = true;

        //初始化定位
        initOnceLocation();

        //开始定位
        startLocationOnce();
    }

    public void stopAmapLocServiceForOnce() {
        if (isOnceLocation) {
            //停止定位
            stopLocation();
            //销毁定位
            destroyLocation();

            isOnceLocation = false;
        }
    }

    public void stopAmapLocService(){
        //停止定位
        stopLocation();
        //关闭后台定位
        locationClient.disableBackgroundLocation(true);
        //销毁定位
        destroyLocation();
        //取消屏幕常亮
        stopScreenOn();

        isRunning = false;
    }

    public boolean isLocationClientStarted(){
        return locationClient != null && locationClient.isStarted();
    }

    private void setScreenKeepOn(){
        //如果为单次定位，则无需开启屏幕常亮模式
        if (isOnceLocation)
            return;

        BaseApp baseApp = BaseApp.getInstance();
        boolean isKeepScreenOn = baseApp.isbKeepScreenOn();
        boolean isKeepScreenWakeup = baseApp.isbKeepScreenWakeup();
        int iKeepScreenWakeupTime = baseApp.getKeepScreenWakeupTime() * 1000;
        Context context = baseApp.getApplicationContext();
        mbKeepScreenWakeup = false;
        if (isKeepScreenOn){
            alarmReceiver = new AlarmReceiver();
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
            context.registerReceiver(alarmReceiver, intentFilter);
            mbRegisterScreenOn = true;
        }else {
            mbRegisterScreenOn = false;
            alarmReceiver = null;
            if (isKeepScreenWakeup){
                AlarmUtils.getInstance().startBroadcast(iKeepScreenWakeupTime, AlarmReceiver.class, ACTION_AMAP_WAKEUP, REQCODE_AMAP_WAKEUP);
                mbKeepScreenWakeup = true;
            }
        }
    }

    private void stopScreenOn(){
        Context context = BaseApp.getInstance().getApplicationContext();
        if (alarmReceiver != null && mbRegisterScreenOn){
            alarmReceiver.releaseWakeLock();

           context.unregisterReceiver(alarmReceiver);
        }
        mbRegisterScreenOn = false;

        if (mbKeepScreenWakeup){
            AlarmUtils.getInstance().stopBroadcast(AlarmReceiver.class, ACTION_AMAP_WAKEUP, REQCODE_AMAP_WAKEUP);
        }
        mbKeepScreenWakeup = false;
    }
}
