package com.tofly.ghrq_route.module.gps;

import android.annotation.SuppressLint;
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.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.provider.Settings;
import android.text.TextUtils;

import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.Point;
import com.mgq.base.utils.logger.LogRecorder;
import com.mgq.base.utils.net.NetworkStatus;
import com.mgq.base.utils.toast.ToastUtil;
import com.tofly.ghrq_route.R;
import com.tofly.ghrq_route.base.BaseApp;
import com.tofly.ghrq_route.base.ui.BaseMapController;
import com.tofly.ghrq_route.base.C;
import com.tofly.ghrq_route.base.URLResponseCode;
import com.tofly.ghrq_route.module.OfflineWork.domain.OfflineWorkEvent;
import com.tofly.ghrq_route.module.buildManage.BuildTool;
import com.tofly.ghrq_route.module.buildManage.domain.BuildHandleDataBean;
import com.tofly.ghrq_route.module.buildManage.domain.BuildManageEvent;
import com.tofly.ghrq_route.module.deviceInfo.DeviceInfoTool;
import com.tofly.ghrq_route.module.gps.controller.GPSCallBack;
import com.tofly.ghrq_route.module.gps.controller.GPSController;
import com.tofly.ghrq_route.module.gps.domain.CheckGPSDataBean;
import com.tofly.ghrq_route.module.gps.domain.GPSDataBean;
import com.tofly.ghrq_route.module.gps.domain.LocationGPSDataBean;
import com.tofly.ghrq_route.module.gps.domain.SignPathEvent;
import com.tofly.ghrq_route.module.plan.PlanTool;
import com.tofly.ghrq_route.module.plan.controller.PlanCallBack;
import com.tofly.ghrq_route.module.plan.controller.PlanController;
import com.tofly.ghrq_route.module.plan.domain.OfflinePathBean;
import com.tofly.ghrq_route.module.plan.domain.PlanBean;
import com.tofly.ghrq_route.module.sqlite.DBDaoHelper;
import com.tofly.ghrq_route.module.user.domain.UserBean;
import com.tofly.ghrq_route.common.ui.activity.UiBuildManage;
import com.tofly.ghrq_route.common.ui.activity.UiPlan;
import com.tofly.ghrq_route.common.ui.activity.UiPlanDetail;
import com.tofly.ghrq_route.common.util.AlarmUtils.AlarmUtils;
import com.tofly.ghrq_route.common.util.ArcgisUtils.ArcgisUtils;
import com.tofly.ghrq_route.common.util.date.DateUtils;
import com.tofly.ghrq_route.common.util.net.NetUtil;
import com.tofly.ghrq_route.common.util.sharedPreference.SharePreUtil;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import static com.tofly.ghrq_route.base.C.UPLOAD_SAVED_LIMIT_MAX_COUNT;

/**
 * Created by Amu on 2017/4/20.
 */

public class GpsTool {

    private static final String TAG = GpsTool.class.getSimpleName();

    private static String PROVIDER = LocationManager.GPS_PROVIDER;
    private static final String GPS_PROVIDER = LocationManager.GPS_PROVIDER;
    private static final String NETWORK_PROVIDER = LocationManager.NETWORK_PROVIDER;

    /*检测半径，单位米*/
    private int CHECK_RADIUS = BaseApp.getInstance().getPointCheckRadius();

    private int CHECK_RADIUS_DEVICE = BaseApp.getInstance().getPointCheckRadiusDevice();

    /*检测半径，单位米*/
    private int CHECK_RADIUS_CAR = BaseApp.getInstance().getPointCheckRadiusCar();

    /*工地检测半径，单位米*/
    private int BUILD_CHECK_RADIUS = BaseApp.getInstance().getBuildCheckRadius();

    /*有效时速， 单位km/h*/
    private int CHECK_MAX_SPEED = BaseApp.getInstance().getPointMaxSpeed();

    /*有效时速， 单位km/h*/
    private int CHECK_MAX_SPEED_CAR = BaseApp.getInstance().getPointMaxSpeedCar();

    /*轨迹最大有效精度，单位米*/
    private int CHECK_MAX_PRECISION = BaseApp.getInstance().getPointCheckPrecison();

    /*轨迹最大有效速度，单位km/h*/
    private int CHECK_MAX_GPS_SPEED = BaseApp.getInstance().getPointMaxGpsSpeed();

    /*Gps隔多少次轨迹震动一次*/
    private int GPS_VIBRATE_PERIOD = BaseApp.getInstance().getiGpsVibratePeriodTime();

    private int mGpsVibrateTime = 0;

    private int mUploadGpsTimes = 0;

    /*检测单位，一千米*/
    public static final int CHECK_UNITS = 1000;

    private double CHECK_SCALE = (double) CHECK_UNITS / CHECK_RADIUS;

    private double CHECK_SCALE_DEVICE = (double) CHECK_UNITS / CHECK_RADIUS_DEVICE;

    private double CHECK_SCALE_CAR = (double) CHECK_UNITS / CHECK_RADIUS_CAR;

    private double BUILD_CHECK_SCALE = (double) CHECK_UNITS / BUILD_CHECK_RADIUS;

    public static final double D_LNG_RADIUS_UNIT = Math.cos(Math.toRadians(23.14));

    /*1km->经度*/
    public static final double D_LNG_SCALE = 1 / (6369 * D_LNG_RADIUS_UNIT * 2 * Math.PI / 360);

    /*1km->维度*/
    public static final double D_LAT_SCALE = 1 / (6369 * 2 * Math.PI / 360);

    private static final int LOC_TIME = 1000/*10000*/; //设置每获取定位的时间间隔，单位：ms

    private static final int LOC_DISTANCE = 0; //设置每获取定位的间距，单位：m

    private static final int SECTION_VALID_TIME_OFFSET = 5 * 60 * 1000; //单位ms

    private static final int SAME_PLACE_VALID_TIME_OFFSET = 10 * 60 * 1000; //单位ms

    private static final int GPS_VALID_PRECISION = 50; //单位meters

    private static final double GPS_VALID_WALK_SPEED = 3.0f; //单位meters/s

    private static final double GPS_VALID_CAR_SPEED = 27.7777778f; //单位meters/s （100km/h）

    private static GpsTool gpsTool = null;

    private Context mContext;

    private List<GpsSatellite> gpsSatelliteList = new ArrayList<>(); // 卫星信号

    private static int gps_no_result = 0;

    private LocationManager mLocationManager;

    private Location mLocation;

    private GPSDataBean mLastLocation;

    private boolean isRunning = false;

    private boolean isGpsValid = false;

    private PlanController planController;

    private GPSController gpsController;

    private DBDaoHelper dbDaoHelper;

    private NotificationManager notificationManager = null;

    private Timer timerLocation = null;

    private final static int LOCATION_TYPE_GPS = 1;
    private final static int LOCATION_TYPE_CELL = 2;
    private final static int LOCATION_TYPE_WIFI = 3;

    private static int CONNECTION_ERR_COUNT = 0;

    private GpsTool() {
        initLocation();
    }

    public static synchronized GpsTool getInstance() {
        if (gpsTool == null) {
            gpsTool = new GpsTool();
        }
        return gpsTool;
    }

    private void initLocation() {
        Context context = BaseApp.getInstance();

        dbDaoHelper = DBDaoHelper.getInstance();

        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        notificationManager = (NotificationManager) BaseApp.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
    }

    @SuppressLint("MissingPermission")
    public void observeGpsStar() {
        mLocationManager.addGpsStatusListener(gpsStatusListener);
    }

    public void stopObserveGpsStar() {
        mLocationManager.removeGpsStatusListener(gpsStatusListener);
    }

    public void updateCheckScale() {
        CHECK_RADIUS = BaseApp.getInstance().getPointCheckRadius();
        CHECK_SCALE = (double) CHECK_UNITS / CHECK_RADIUS;
        CHECK_SCALE_DEVICE = (double) CHECK_UNITS / CHECK_RADIUS_DEVICE;
        CHECK_SCALE_CAR = (double) CHECK_UNITS / CHECK_RADIUS_CAR;
        BUILD_CHECK_RADIUS = BaseApp.getInstance().getBuildCheckRadius();
        BUILD_CHECK_SCALE = (double) CHECK_UNITS / BUILD_CHECK_RADIUS;
        CHECK_MAX_SPEED = BaseApp.getInstance().getPointMaxSpeed();
        CHECK_MAX_SPEED_CAR = BaseApp.getInstance().getPointMaxSpeedCar();
        CHECK_MAX_PRECISION = BaseApp.getInstance().getPointCheckPrecison();
        CHECK_MAX_GPS_SPEED = BaseApp.getInstance().getPointMaxGpsSpeed();
    }

    public void updateVibratePeriod(){
        GPS_VIBRATE_PERIOD = BaseApp.getInstance().getiGpsVibratePeriodTime();
    }

    public double getRouteCheckScale(){
        return CHECK_SCALE;
    }

    public double getRouteCheckScaleDevice(){
        return CHECK_SCALE_DEVICE;
    }

    public double getRouteCheckScaleCar(){
        return CHECK_SCALE_CAR;
    }

    public double getBuildCheckScale(){
        return BUILD_CHECK_SCALE;
    }

    public static String getPROVIDER() {
        return PROVIDER;
    }

    public int getGpsStar() {
        int star = 0;
        if (mLastLocation != null) {
            star = mLastLocation.getGps_star();
        }
        return star;
    }

    public int getUploadGpsTimes() {
        return mUploadGpsTimes;
    }

    void resetUploadGpsTimes() {
        mUploadGpsTimes = 0;
    }

    @SuppressLint("MissingPermission")
    public void startLocating(Context context) {
        mContext = context;

        isRunning = true;

        //GPS是否正常启动
        //openGpsSettings();

        PROVIDER = LocationManager.GPS_PROVIDER;

        mLocation = mLocationManager.getLastKnownLocation(PROVIDER);
        /*if (mLocation == null) */
        {
            mLocationManager.requestLocationUpdates(PROVIDER, LOC_TIME, LOC_DISTANCE, locationListener, Looper.getMainLooper());
        }
        observeGpsStar();

        //getLocationPoiByTimer();
    }

    public void stopLocating() {
        isRunning = false;
        if (locationListener != null)
            mLocationManager.removeUpdates(locationListener);
        stopObserveGpsStar();
    }

    // 位置监听
    @SuppressLint("MissingPermission")
    private LocationListener locationListener = new LocationListener() {
        // 位置信息变化时触发
        @Override
        public void onLocationChanged(Location location) {
            if (location != null){
                mLocation = location;
                BaseApp.mLocation = location;
            }

            if (location == null)
                location = new Location(PROVIDER);

            UserBean userBean = BaseApp.getInstance().getLoginUser();
            //getLocationPoi(userBean);
            saveGpsLoctionLog(location, userBean);

            /*String check_time = DateUtils.getDate(new Date().getTime());
            boolean isPast = checkGpsDataIsPastSecond(check_time);
            if (isPast){
                getLocationPoi();
            }*/
        }

        // GPS状态变化时触发
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch (status) {
                // GPS状态为可见时
                case LocationProvider.AVAILABLE:
                    PROVIDER = GPS_PROVIDER;
                    mLocationManager.requestLocationUpdates(PROVIDER, LOC_TIME, LOC_DISTANCE, locationListener);
                    break;
                // GPS状态为服务区外时
                case LocationProvider.OUT_OF_SERVICE:
                    PROVIDER = NETWORK_PROVIDER;
                    mLocationManager.requestLocationUpdates(PROVIDER, LOC_TIME, LOC_DISTANCE, locationListener);
                    break;
                // GPS状态为暂停服务时
                case LocationProvider.TEMPORARILY_UNAVAILABLE:
                    PROVIDER = NETWORK_PROVIDER;
                    mLocationManager.requestLocationUpdates(PROVIDER, LOC_TIME, LOC_DISTANCE, locationListener);
                    break;
            }
        }

        // GPS开启时触发
        @Override
        public void onProviderEnabled(String provider) {
            Location location = mLocationManager.getLastKnownLocation(provider);
            if (location != null) {
                mLocation = location;
            }
        }

        // GPS禁用时触发
        @Override
        public void onProviderDisabled(String provider) {

        }
    };

    private LocationListener gpsListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            if (location != null) {
                PROVIDER = GPS_PROVIDER;
                mLocationManager.removeUpdates(gpsListener);
                return;
            }
        }

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

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };

    private void saveGPSDataToLocation(GPSDataBean location, String check_time_ms) {
// 当轨迹点不是异常点时进行保存
        /*if (location.getIsValid() == 1) */{
            LocationGPSDataBean locationGPSDataBean = new LocationGPSDataBean();
            locationGPSDataBean.setLongitude(Double.parseDouble(location.getLng()));
            locationGPSDataBean.setLatitude(Double.parseDouble(location.getLat()));
            locationGPSDataBean.setDate(DateUtils.getDateMS());
            locationGPSDataBean.setGps_time(check_time_ms);
            locationGPSDataBean.setDay(DateUtils.getYMD());
            locationGPSDataBean.setSection(SharePreUtil.getSignSection(DateUtils.getYMD()));
            locationGPSDataBean.setIsValid(location.getIsValid());
            locationGPSDataBean.setState(location.getState());
            if (dbDaoHelper != null) {
                long gpsSId = dbDaoHelper.saveLocationGPSData(locationGPSDataBean);
                location.setSid(gpsSId);
            }
//            实时刷新界面上的轨迹点
            EventBus.getDefault().post(new SignPathEvent(
                    locationGPSDataBean, BaseMapController.SIGN_PATH_UPDATE));
        }
    }

    public boolean isGpsOpen() {
        return mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    //  开启GPS定位开关的提示
    private void openGpsSettings() {
        Context context = BaseApp.getInstance();
        if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            ToastUtil.showToast(context, "GPS未打开，请开启GPS！");
            gotoSystemGpsSetting();
        }
    }

    public void checkGpsSettingOpen(){
        Context context = BaseApp.getInstance();
        boolean isEnabled = isLocationEnabled();
        if (!isEnabled){
            ToastUtil.showToast(context, "GPS未打开，请开启GPS！");
            gotoSystemGpsSetting();
        }
    }

    public void gotoSystemGpsSetting(){
        Context context = BaseApp.getInstance();
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);
    }

    /**
     * 判断定位服务是否开启
     *
     * @param
     * @return true 表示开启
     */
    public boolean isLocationEnabled() {
        int locationMode = 0;
        String locationProviders;
        if (mContext == null)
            mContext = BaseApp.getInstance().getApplicationContext();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                locationMode = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.LOCATION_MODE);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return locationMode != Settings.Secure.LOCATION_MODE_OFF;
        } else {
            locationProviders = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !TextUtils.isEmpty(locationProviders);
        }
    }

    private void saveGpsLoctionLog(Location lastLoc, UserBean userBean){
        if (C.bLogMapToolLocForBaiduArcgis_debug){
            if (mContext == null)
                mContext = BaseApp.getInstance().getApplicationContext();
            String userid = "";
            if (userBean != null)
                userid = userBean.getUserid();
            String lng = String.format("%.6f", lastLoc.getLongitude());
            String lat = String.format("%.6f", lastLoc.getLatitude());
            String check_time = DateUtils.getDateTimeMS();
            String gps_time = DateUtils.getDateTimeMS(lastLoc.getTime());
            String provider = String.valueOf(lastLoc.getProvider());
            String gps_star = String.valueOf(getGpsStar());
            String accuracy = String.format("%.2f", lastLoc.getAccuracy());
            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.writeGpsToolLog(mContext, logMsg, userid);
        }
    }

    private void getLocationPoiByTimer(){
        int period = BaseApp.getInstance().getGpsWakeTime();
        timerLocation = new Timer();
        timerLocation.schedule(new TimerTask() {
            @Override
            public void run() {
                Looper.prepare();
                getLocationPoi();
                Looper.loop();
            }
        }, period, period);
    }

    public void resetTimer(){
        if (timerLocation != null)
            timerLocation.cancel();
        getLocationPoiByTimer();
    }


    @SuppressLint("MissingPermission")
    public void getLocationPoi() {
        //openGpsSettings();
        UserBean userBean = BaseApp.getInstance().getLoginUser();

        Location lastLoc = mLocationManager.getLastKnownLocation(PROVIDER);
        mLocation = lastLoc;
        refreshLocationManager();

        if (userBean != null) {
            boolean isValidLoc = true;
            if (lastLoc == null) {
                isValidLoc = false;
                lastLoc = new Location(PROVIDER);
            }
            isGpsValid = isValidLoc;
            String lng = String.format("%.6f", lastLoc.getLongitude());
            String lat = String.format("%.6f", lastLoc.getLatitude());
            String time = DateUtils.getDate(lastLoc.getTime());
            String check_time = DateUtils.getDate(new Date().getTime());
            String gps_speed = Float.toString(lastLoc.getSpeed());
            int network_type = getProviderType(lastLoc.getProvider());

            GPSDataBean gpsDataBean = new GPSDataBean();
            gpsDataBean.setLng(lng);
            gpsDataBean.setLat(lat);
            gpsDataBean.setNetwork(network_type);
            gpsDataBean.setGpstime(time);
            gpsDataBean.setCheck_time(check_time);
            gpsDataBean.setGps_speed(gps_speed);
            boolean carMode = userBean.isCarMode();
            gpsDataBean.setGps_type(carMode ? 1 : 0);
            gpsDataBean.setCarid(userBean.getCarid());
            int gpsStar = getGpsStar();
            gpsDataBean.setGps_star(gpsStar);
            String accuracy = String.format("%.2f", lastLoc.getAccuracy());
            gpsDataBean.setGps_precision(accuracy);

            checkGpsDataAndUpload(userBean, gpsDataBean, check_time, isValidLoc);
        } else {
            //checkSavedGpsInfo();
        }
    }

    public void checkGpsDataAndUpload(UserBean userBean, GPSDataBean gpsDataBean, String check_time_ms, boolean isValidLoc){
        if (gpsDataBean == null) {
            isGpsValid = false;
            return;
        }

        /*超过服务器设定的时间则上传, 否则返回*/
        int period = BaseApp.getInstance().getGpsWakeTime();
        boolean isPast = checkGpsDataIsPastSecond(period);
        if (!isPast){
            return;
        }

        isGpsValid = true;

        mLocation = new Location(GPS_PROVIDER);
        mLocation.setLongitude(Double.parseDouble(gpsDataBean.getLng()));
        mLocation.setLatitude(Double.parseDouble(gpsDataBean.getLat()));


        /*设置当前轨迹分段*/
        long section = SharePreUtil.getSignSectionToday();
        gpsDataBean.setSection(section);


        mUploadGpsTimes++;
        if (mUploadGpsTimes <= 1)
            return;

        mGpsVibrateTime++;
        boolean isGpsNotify = BaseApp.getInstance().isGpsNotifyOpen();
        boolean isbGpsVibrateOn = BaseApp.getInstance().isGpsVibrateOn();
        boolean bShouldVibrate = mGpsVibrateTime >= GPS_VIBRATE_PERIOD;
        if (isGpsNotify || isbGpsVibrateOn){
            if (mContext == null)
                mContext = BaseApp.getInstance().getApplicationContext();

            String gps_lng = gpsDataBean.getLng();
            String gps_lat = gpsDataBean.getLat();
            ToastUtil.showToast(mContext, "当前GPS坐标： Lng:" + gps_lng + " Lat:" + gps_lat + " Provider: " + PROVIDER + " isValid: " + isValidLoc, true);

            if (isGpsNotify)
                AlarmUtils.playNotificationAlarm();

            if (isbGpsVibrateOn && bShouldVibrate)
                AlarmUtils.playNotificationVibrate(mContext);
        }
        if (bShouldVibrate)
            mGpsVibrateTime = 0;

        if (isValidLoc) {
            double lng = Double.parseDouble(gpsDataBean.getLng());
            double lat = Double.parseDouble(gpsDataBean.getLat());
            Point point = new Point(lng, lat);
            EventBus.getDefault().post(new UiPlan.PlanEvent(UiPlan.PLAN_SERVICE_LOCATION, point));
        }

        boolean isRepate = /*checkGpsDataIsRepeat(gpsDataBean)*/false;  //已取消
        boolean isPast10 = /*checkGpsDataSamePlace(gpsDataBean)*/false;  //已取消
        if (!isRepate) {
            gpsDataBean = checkGpsDataValid(gpsDataBean, isValidLoc);
            /*gpsDataBean = checkGpsDataSectionBySignState(gpsDataBean);*/ //已取消
            /*boolean test = true;
            if (test){
                double lng = Double.parseDouble("106.54166257");
                double lat = Double.parseDouble("29.55993008");
                double lng_plan = 106.5415747440;
                double lat_plan = 29.5602335380;
                double xscale = D_LNG_SCALE / CHECK_SCALE;
                double yscale = D_LAT_SCALE / CHECK_SCALE;
                double xMin = lng - xscale;
                double xMax = lng + xscale;
                double yMin = lat - yscale;
                double yMax = lat + yscale;

                boolean isOver = false;
                if (lng_plan >= xMin && lng_plan <= xMax
                        && lat_plan >= yMin && lat_plan <= yMax)
                    isOver = true;
            }*/

            if (isValidLoc) {
                /*7.当轨迹点valid<>0并且state=null时，判断到位任务*/
                boolean isFloatPoint = (gpsDataBean.getIsValid() == 0);
                boolean needCheckOver = (!isFloatPoint && gpsDataBean.getState() != 0);

                if (needCheckOver) {
                    /*計算到位時間*/
                    checkOfflinePoint(gpsDataBean);

                    /*计算离开时间*/
                    /*checkOfflinePointOffTime(lng, lat, gps_speed, check_time, planMode);*/ //已取消
                }

                /*判断是否有工地任务*/
                boolean hasBuildLogPlan = checkTodayBuildLogPlan();
                /*8.当轨迹点valid<>0并且工地状态为监护中，判断轨迹点与工地点的距离是否超过容差，
                如果超过容差，则将工地状态更新为结束监护*/
                if (!isFloatPoint && hasBuildLogPlan) {
                    checkBuildInPlace(gpsDataBean, isFloatPoint);
                }

                /*保存轨迹点到本地*/
                saveGPSDataToLocation(gpsDataBean, check_time_ms);
            }

            mLastLocation = gpsDataBean;
            boolean isNetConnected = NetworkStatus.isNetworkConnected(BaseApp.getInstance());
            if (isNetConnected) {
                //上传GPS数据
                if (!isPast10){
                    uploadGPSInfo(gpsDataBean, true);
                }

                //checkSavedGpsInfo();
            } else {
                saveGpsInfo(gpsDataBean);
            }
        }
    }

    /*上一个轨迹点如果与当前定位点的本地时间超过服务器设定时间则上传*/
    private boolean checkGpsDataIsPastSecond(int period) {
        boolean isPast = true;
        String check_time = DateUtils.getDate(new Date().getTime());
        CheckGPSDataBean lastCheckGps = dbDaoHelper.getLastCheckGps();
        if (lastCheckGps != null && lastCheckGps.getCheck_time() != null) {
            String lastCheckTime = lastCheckGps.getCheck_time();
            long timeOffset = DateUtils.getTimeOffset(check_time, lastCheckTime);
            isPast = timeOffset >= period;
        }
        return isPast;
    }

    /*上一个轨迹点如果与当前定位点的本地时间相同则忽略*/
    private boolean checkGpsDataIsRepeat(GPSDataBean gpsData) {
        boolean isRepeat = false;
        if (gpsData == null)
            return false;
        CheckGPSDataBean lastCheckGps = dbDaoHelper.getLastCheckGps();
        if (lastCheckGps != null) {
            String lastCheckTime = lastCheckGps.getCheck_time();
            String checkTime = gpsData.getCheck_time();
            if (lastCheckTime != null && lastCheckTime.equals(checkTime)){
                isRepeat = true;
            }
        }
        return isRepeat;
    }

    /*通过上一个轨迹点状态当前定位点是否在相同的地方超过10分钟*/
    private boolean checkGpsDataSamePlace(GPSDataBean gpsData){
        boolean isPast10 = false;
        if (gpsData == null)
            return false;

        CheckGPSDataBean lastCheckGps = dbDaoHelper.getLastCheckGps();
        long section = 1;
        if (lastCheckGps != null && lastCheckGps.getLng() != null && lastCheckGps.getLat() != null) {
            double lastLng = Double.parseDouble(lastCheckGps.getLng());
            double lastLat = Double.parseDouble(lastCheckGps.getLat());
            double currentLng = Double.parseDouble(gpsData.getLng());
            double currentLat = Double.parseDouble(gpsData.getLat());
            if (lastLng >= 0 && lastLat >= 0 && currentLng >= 0 && currentLat >= 0) {
                long timeSpan = 0;
                if (lastLng == currentLng && lastLat == currentLat){
                    String lastCheckTime = lastCheckGps.getCheck_time();
                    String checkTime = gpsData.getCheck_time();
                    long timeOffset = DateUtils.getTimeOffset(checkTime, lastCheckTime);
                    timeSpan = lastCheckGps.getTimespan() + timeOffset;
                }
                lastCheckGps.setTimespan(timeSpan);
                dbDaoHelper.saveLastCheckGps(lastCheckGps);

                isPast10 = timeSpan >= SAME_PLACE_VALID_TIME_OFFSET;
            }
        }
        return isPast10;
    }

    /*暂时未启用*/
    private GPSDataBean checkGpsDataSection(GPSDataBean gpsData) {
        if (gpsData == null)
            return gpsData;
        CheckGPSDataBean lastCheckGps = dbDaoHelper.getLastCheckGps();
        long section = 1;
        if (lastCheckGps != null) {
            long lastSection = lastCheckGps.getSection();
            String lastCheckTime = lastCheckGps.getCheck_time();
            String checkTime = gpsData.getCheck_time();

            /*车巡、人巡切换后分段*/
            if (lastCheckGps.getGps_type() != gpsData.getGps_type()) {
                lastSection++;
            }

            /*当前轨迹点与上一个点时间间隔超过5分钟进行分段，*/
            long timeOffset = DateUtils.getTimeOffset(checkTime, lastCheckTime);
            if (timeOffset >= SECTION_VALID_TIME_OFFSET) {
                lastSection++;
            }

            /*每段轨迹的点不能超过1000个点*/
            section = lastSection;
            if (section > 1000)
                section = 1;
        }
        gpsData.setSection(section);
        lastCheckGps = new CheckGPSDataBean(gpsData);
        dbDaoHelper.saveLastCheckGps(lastCheckGps);
        return gpsData;
    }

    public void setGpsDataSection(int section){
/*        CheckGPSDataBean lastCheckGps = dbDaoHelper.getLastCheckGps();
        if (lastCheckGps != null) {
*//*            long lastSection = lastCheckGps.getSection();
            lastSection++;*//*
            lastCheckGps.setSection(section);
            dbDaoHelper.saveLastCheckGps(lastCheckGps);
        }else {
            lastCheckGps = new CheckGPSDataBean();
            lastCheckGps.setSection(section);
            dbDaoHelper.saveLastCheckGps(lastCheckGps);
        }*/
        SharePreUtil.setSignSectionToday(section);
    }

    /*通过签到状态判定分段*/
    private GPSDataBean checkGpsDataSectionBySignState(GPSDataBean gpsData) {
        if (gpsData == null)
            return gpsData;
        CheckGPSDataBean lastCheckGps = dbDaoHelper.getLastCheckGps();
        long section = 1;
        long timeSpan = 0;
        if (lastCheckGps != null) {
            long lastSection = lastCheckGps.getSection();
            section = lastSection;
            timeSpan = lastCheckGps.getTimespan();
        }
        gpsData.setSection(section);
        lastCheckGps = new CheckGPSDataBean(gpsData);
        lastCheckGps.setTimespan(timeSpan);
        dbDaoHelper.saveLastCheckGps(lastCheckGps);
        return gpsData;
    }

    private static boolean TEST_GPS_SPEED = false;
    private GPSDataBean checkGpsDataValid(GPSDataBean gpsData, boolean isGpsValid) {
        if (gpsData == null)
            return gpsData;

        /*如果上一个轨迹点为空，或者上一个轨迹点的分段数，巡检类型同当前轨迹点不同，则视为新开始的一段轨迹
        * 的第一个轨迹点*/
        boolean isNewSectionData = false;
        CheckGPSDataBean lastCheckGps = dbDaoHelper.getLastCheckGps();
        if (lastCheckGps == null || lastCheckGps.getSection() != gpsData.getSection()
                || lastCheckGps.getGps_type() != gpsData.getGps_type()){
            isNewSectionData = true;
        }

        /*1.判断是是否当前点是否为漂移点
            如果当前点定位精度大于等于200米(默认，通过系统配置获取)标记这个轨迹点为漂移点*/
        String gpsPrecision = gpsData.getGps_precision();
        if (gpsPrecision != null && !gpsPrecision.isEmpty()) {
            int precision = Integer.parseInt(gpsPrecision);
            if (precision < CHECK_MAX_PRECISION) {
                gpsData.setIsValid(1);
            }else {
                gpsData.setIsValid(0);
                gpsData.setSpeed("0");
                gpsData.setDistance("0");
                gpsData.setGps_timespan("0");
                gpsData.setState(0);
                dbDaoHelper.saveLastCheckGps(new CheckGPSDataBean(gpsData));
                return gpsData;
            }
        }

        /*新的一端轨迹的第一个轨迹点，不参与速度等运算*/
        if (!isNewSectionData){
            String lastGpsTime = lastCheckGps.getGpstime();
            String gpsTime = gpsData.getGpstime();

            long timeOffset = DateUtils.getTimeOffset(gpsTime, lastGpsTime);

            //2.判断当前轨迹点xy与上一点的xy是否相同
            if (gpsData.getLng().equals(lastCheckGps.getLng()) &&
                    gpsData.getLat().equals(lastCheckGps.getLat())){
                gpsData.setSpeed("0");
                gpsData.setDistance("0");
                gpsData.setGps_timespan(String.valueOf(timeOffset / 1000));
                gpsData.setIsValid(lastCheckGps.getIsValid());
                gpsData.setState(0);
                dbDaoHelper.saveLastCheckGps(new CheckGPSDataBean(gpsData));
                return gpsData;
            }

            /*3.如果当前轨迹点valid=1，上一轨迹点valid=0，
                则当前轨迹点valid=2代表这个轨迹点的间距、时间间隔需要重新计算*/
            if (gpsData.getIsValid() == 1 && lastCheckGps.getIsValid() == 0){
                gpsData.setSpeed("0");
                gpsData.setDistance("0");
                gpsData.setGps_timespan("0");
                gpsData.setIsValid(2);
                dbDaoHelper.saveLastCheckGps(new CheckGPSDataBean(gpsData));
                return gpsData;
            }

            /*4.如果gpstime小于上一个轨迹点，则当前轨迹点valid=2（代表这个轨迹点的间距、时间间隔需要重新计算）
            并且这个点不能作为上一点，因为这个是历史点*/
            int compare = DateUtils.getTimeCompare(gpsTime, lastGpsTime);
            if (compare < 0){
                gpsData.setSpeed("0");
                gpsData.setDistance("0");
                gpsData.setGps_timespan("0");
                gpsData.setIsValid(2);
                return gpsData;
            }

            /*5.计算当前轨迹点与上一点的距离，时间间隔，速度*/
            double lastLng = Double.parseDouble(lastCheckGps.getLng());
            double lastLat = Double.parseDouble(lastCheckGps.getLat());
            double currentLng = Double.parseDouble(gpsData.getLng());
            double currentLat = Double.parseDouble(gpsData.getLat());
            double speed = 0;
            if (lastLng != 0 && lastLat != 0 && currentLng != 0 && currentLat != 0) {

/*                polyline.startPath(lastLng, lastLat);
                polyline.lineTo(currentLng, currentLat);*/
                Point point0 = new Point(lastLng, lastLat, ArcgisUtils.getWgs84Spatial());
                Point point1 = new Point(currentLng, currentLat, ArcgisUtils.getWgs84Spatial());
                double distance = ArcgisUtils.getTwoPointDistance1(point0, point1);
                //double distance = GeometryEngine.distanceBetween(point0, point1);
/*                double distance = GeometryEngine.geodesicLength(polyline
                        , SpatialReference.create(4490)
                        , (LinearUnit) Unit.create(9001));*/
                speed = (distance * 3600 / timeOffset); //单位km/h
                String str_speed = String.format("%.2f", speed);
                gpsData.setSpeed(str_speed);
                String str_distance = String.format("%.2f", distance);
                gpsData.setDistance(str_distance);
                gpsData.setGps_timespan(String.valueOf(timeOffset / 1000));
            }

            /*6.判断人巡状态下速度是否>10km/h，车巡状态下速度是否>40km/h，
            如果满足以上任一条件，则轨迹点的state=0（代表这个轨迹点是非到位点），否则state=null*/
            UserBean userBean = BaseApp.getInstance().getLoginUser();
            boolean hasCarPlan = dbDaoHelper.hasCarModePlan(userBean.getUserid());
            int check_speed = hasCarPlan ? CHECK_MAX_SPEED_CAR : CHECK_MAX_SPEED;
            if (speed > check_speed){
                gpsData.setState(0);
            }

            /*轨迹速度超过最大轨迹速度100km/h就设置成无效轨迹点 valid=0 */
            if (speed > CHECK_MAX_GPS_SPEED){
                gpsData.setIsValid(0);
            }

            dbDaoHelper.saveLastCheckGps(new CheckGPSDataBean(gpsData));
        }else {
            dbDaoHelper.saveLastCheckGps(new CheckGPSDataBean(gpsData));
        }
        return gpsData;
    }

    private GPSDataBean computeGpsSpeedDistance(GPSDataBean gpsData) {
        CheckGPSDataBean lastValidCheckGps = dbDaoHelper.getLastCheckGps();
        //测试gps速度判断
        if (TEST_GPS_SPEED) {
            lastValidCheckGps = new CheckGPSDataBean();
            lastValidCheckGps.setLng("106.5170075");
            lastValidCheckGps.setLat("29.576519");
            lastValidCheckGps.setGpstime("2018-02-27 20:10:11");
            lastValidCheckGps.setCheck_time("2018-02-27 20:10:11");
            lastValidCheckGps.setSection(3);
            lastValidCheckGps.setGps_type(0);
        }
        if (lastValidCheckGps != null &&
                lastValidCheckGps.getLng() != null && lastValidCheckGps.getLat() != null
                && gpsData != null) {
            //当前点与上一个正常点同为车巡或者人巡模式，并且属于同一分段则计算距离跟速度
            if (lastValidCheckGps.getGps_type() == gpsData.getGps_type() &&
                    lastValidCheckGps.getSection() == gpsData.getSection()) {
                String lastCheckTime = lastValidCheckGps.getCheck_time();
                String checkTime = gpsData.getCheck_time();
                long timeOffset = DateUtils.getTimeOffset(checkTime, lastCheckTime);
                double lastLng = Double.parseDouble(lastValidCheckGps.getLng());
                double lastLat = Double.parseDouble(lastValidCheckGps.getLat());
                double currentLng = Double.parseDouble(gpsData.getLng());
                double currentLat = Double.parseDouble(gpsData.getLat());
                if (lastLng != 0 && lastLat != 0 && currentLng != 0 && currentLat != 0) {
                    Point point0 = new Point(lastLng, lastLat);
                    Point point1 = new Point(currentLng, currentLat);
                    double distance = GeometryEngine.distanceBetween(point0, point1);
/*                    Polyline polyline = new Polyline();
                    polyline.startPath(lastLng, lastLat);
                    polyline.lineTo(currentLng, currentLat);
                    double distance = GeometryEngine.geodesicLength(polyline
                            , SpatialReference.create(4490)
                            , (LinearUnit) Unit.create(9001));*/
                    double speed = (distance * 3600 / timeOffset); //单位km/h

                    String str_speed = String.format("%.2f", speed);
                    gpsData.setSpeed(str_speed);
                    String str_distance = String.format("%.2f", distance);
                    gpsData.setDistance(str_distance);
                    gpsData.setGps_timespan(String.valueOf(timeOffset / 1000));

                    String msg = "lastTime:" + lastValidCheckGps.getCheck_time() + "curTime:" + gpsData.getCheck_time()
                            + "\n" + "距离: " + distance + " 耗时: " + String.valueOf(timeOffset / 1000) + " 速度: " + speed;
                    ToastUtil.showToast(mContext, msg);
                }
            }
        }
        return gpsData;
    }

    private int getProviderType(String provider) {
        int type = LOCATION_TYPE_GPS;
        if (provider != null) {
            if (provider.equals(GPS_PROVIDER)) {
                type = LOCATION_TYPE_GPS;
            } else if (provider.equals(NETWORK_PROVIDER)) {
                int networkState = NetUtil.getNetworkState(BaseApp.getInstance());
                if (networkState == NetUtil.NETWORN_WIFI) {
                    type = LOCATION_TYPE_WIFI;
                } else if (networkState == NetUtil.NETWORN_MOBILE) {
                    type = LOCATION_TYPE_CELL;
                }
            }
        }
        return type;
    }

    private void saveGpsInfo(GPSDataBean gpsDataBean) {
        String gpsId = UUID.randomUUID().toString();
        gpsDataBean.setGps_id(gpsId);
        dbDaoHelper.insertOrUpdateGPSData(gpsDataBean);

        EventBus.getDefault().post(new DeviceInfoTool.DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_NEW_SAVED_GPS, null));
    }

    private void saveLastGpsInfo(GPSDataBean gpsDataBean) {
        String todayDate = DateUtils.getYMD();
        todayDate = String.format("%s_1", todayDate);
        gpsDataBean.setGps_id(todayDate);
        dbDaoHelper.insertOrUpdateGPSData(gpsDataBean);
    }

    private void saveLastValidGpsInfo(GPSDataBean gpsDataBean) {
        String gpsId = UUID.randomUUID().toString();
        gpsDataBean.setGps_id(gpsId);
        dbDaoHelper.insertOrUpdateGPSData(gpsDataBean);
    }

    public boolean checkTodayBuildLogPlan() {
        BuildTool buildTool = BuildTool.getInstance();
        return buildTool.checkTodayHasBuildLogPlan(mContext);
    }

    public long getUnUploadPointsCount() {
        UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (userBean == null)
            return 0;

        String user_id = userBean.getUserid();
        int planMode = userBean.getCar_mode();
        return dbDaoHelper.getUnUploadPointsCount(user_id, planMode);
    }

    public void checkPathOverUpload(final PlanCallBack planCallBack) {
        checkPathOverUpload(planCallBack, C.UPLOAD_SAVED_LIMIT_BIG_COUNT);
    }

    public void checkPathOverUpload(final PlanCallBack planCallBack, int total_limit) {
        final UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (userBean == null) {
            if (planCallBack != null)
                planCallBack.onUpdatePointOver(true, 0, "", null);
            return;
        }

        if (mContext == null)
            mContext = BaseApp.getInstance().getApplicationContext();
        if (planController == null)
            planController = new PlanController(mContext);

        uploadOverPoints(userBean, total_limit, planCallBack);
    }

    private void uploadOverPoints(UserBean userBean, int total_limit, final PlanCallBack planCallBack){
        int planMode = userBean.getCar_mode();
        String user_id = userBean.getUserid();
        /*获取未上传巡检点计划已到点*/
        final List<OfflinePathBean> pathBeanPointList = dbDaoHelper.getUnUploadPathPoint(user_id, planMode, total_limit);
        if (pathBeanPointList != null && pathBeanPointList.size() > 0) {
            planController.updatePointOver(userBean.getToken(), pathBeanPointList, new PlanCallBack() {
                @Override
                public void onUpdatePointOver(boolean isSuccess, int errorCode, String errMsg, List<String> transferIds) {
                    super.onUpdatePointOver(isSuccess, errorCode, errMsg, transferIds);
                    if (isSuccess) {
                        for (OfflinePathBean pathBean : pathBeanPointList) {
                            pathBean.setIsupload(1);
                        }
                        dbDaoHelper.updateOfflinePaths(pathBeanPointList);
                        /*该点的计划已经转移，删除该点*/
                        if (transferIds != null && transferIds.size() > 0) {
                            dbDaoHelper.deletPlanPathBeanById(transferIds);
                        }
                        overPointUpdateUiPlanDetail(pathBeanPointList);
                    } else {

                    }
                    if (planCallBack != null)
                        planCallBack.onUpdatePointOver(isSuccess, errorCode, errMsg, transferIds);
                }
            });
        }else {
            if (planCallBack != null)
                planCallBack.onUpdatePointOver(true, 0, "", null);
        }
    }

    private void overPointUpdateUiPlanDetail(List<OfflinePathBean> pathBeanPointList ){
        Map<String, List<OfflinePathBean>> overMaps = new HashMap<>();
        for (OfflinePathBean path : pathBeanPointList)
        {
            if (overMaps.containsKey(path.getPlan_id())) {
                List<OfflinePathBean> childPaths = overMaps.get(path.getPlan_id());
                if (childPaths == null)
                    childPaths = new ArrayList<>();
                childPaths.add(path);
            } else {
                List<OfflinePathBean> childPaths = new ArrayList<>();
                childPaths.add(path);
                overMaps.put(path.getPlan_id(), childPaths);
            }
        }
        if (overMaps != null && overMaps.size() > 0) {
            EventBus.getDefault().post(new UiPlan.PlanEvent(UiPlan.PLAN_POINT_OVER, overMaps));
        }
    }

    private void checkPathLeftTimeUpload(){

    }

    public void checkSavedGpsInfo(final GPSCallBack gpsCallBack) {
        UserBean user = BaseApp.getInstance().getLoginUser();
        if (user == null){
            if (gpsCallBack != null)
                gpsCallBack.onUploadBatchGpsInfo(true, 0, "", null);
            return;
        }

        final List<GPSDataBean> savedGpsList = dbDaoHelper.getSavedGpsList(UPLOAD_SAVED_LIMIT_MAX_COUNT);
        if (savedGpsList.size() > 0) {
            if (mContext == null)
                mContext = BaseApp.getInstance().getApplicationContext();
            if (gpsController == null)
                gpsController = new GPSController(mContext);
            gpsController.uploadBatchGpsInfo(mContext, savedGpsList, new GPSCallBack() {
                @Override
                public void onUploadBatchGpsInfo(boolean isSuccess, int errorCode, String errMsg, List<GPSDataBean> repeatDatas) {
                    super.onUploadBatchGpsInfo(isSuccess, errorCode, errMsg, repeatDatas);
                    if (isSuccess) {
                        dbDaoHelper.deleteSavedGps(savedGpsList);
                    } else {
                        if (errorCode == URLResponseCode.ErrorCode.UNKNOWN_ERROR) {
                            if (repeatDatas != null && repeatDatas.size() > 0) {
                                dbDaoHelper.deleteSavedGps(repeatDatas);
                            }
                        }
                    }

                    EventBus.getDefault().post(new OfflineWorkEvent(OfflineWorkEvent.OFFLINE_JOB_UPLOAED));

                    if (gpsCallBack != null)
                        gpsCallBack.onUploadBatchGpsInfo(isSuccess, errorCode, errMsg, repeatDatas);
                }
            });
        }else {
            if (gpsCallBack != null)
                gpsCallBack.onUploadBatchGpsInfo(true, 0, "", null);
        }
    }

    public void uploadGPSInfo(final GPSDataBean gpsData, boolean saveOnFail) {
        if (gpsData != null) {
            if (mContext == null)
                mContext = BaseApp.getInstance().getApplicationContext();
            if (gpsController == null)
                gpsController = new GPSController(mContext);
            gpsController.uploadGpsInfo(mContext, gpsData, new GPSCallBack() {
                @Override
                public void onUploadGpsInfo(boolean isSuccess, int errorCode, String errMsg) {
                    super.onUploadGpsInfo(isSuccess, errorCode, errMsg);
                    if (isSuccess) {
                        CONNECTION_ERR_COUNT = 0;
                    } else {
                        //保存在本地
                        if (saveOnFail)
                            saveGpsInfo(gpsData);
                        CONNECTION_ERR_COUNT++;
                    }
                }
            });
        }
    }

    public void updateGPSStatus(final GPSDataBean gpsData) {
        if (gpsData != null) {
            if (mContext == null)
                mContext = BaseApp.getInstance().getApplicationContext();
            if (gpsController == null)
                gpsController = new GPSController(mContext);
            gpsController.updateGpsStatus(mContext, gpsData, new GPSCallBack() {
                @Override
                public void onUploadGpsInfo(boolean isSuccess, int errorCode, String errMsg) {
                    super.onUploadGpsInfo(isSuccess, errorCode, errMsg);
                }
            });
        }
    }

    private void checkOfflinePoint(GPSDataBean gpsDataBean) {
        final int over = OfflinePathBean.POINTLINE_IS_OVER;

        double lng = Double.parseDouble(gpsDataBean.getLng());
        double lat = Double.parseDouble(gpsDataBean.getLat());
        String gps_speed = gpsDataBean.getGps_speed();
        String check_time = gpsDataBean.getCheck_time();

        /*未到点巡检线的点*/
        UserBean user = BaseApp.getInstance().getLoginUser();
        String userid = user.getUserid();
        List<OfflinePathBean> nowOverPaths = getOverPathListByPlan(userid, lng, lat);
        Map<String, List<OfflinePathBean>> overMaps = new HashMap<>();
        if (nowOverPaths != null) {
            for (OfflinePathBean path : nowOverPaths) {
                path.setIsover(over);
                path.setCheck_time(check_time);
                path.setGps_speed(gps_speed);
                sendNotification(path);
                if (overMaps.containsKey(path.getPlan_id())) {
                    List<OfflinePathBean> childPaths = overMaps.get(path.getPlan_id());
                    if (childPaths == null)
                        childPaths = new ArrayList<>();
                    childPaths.add(path);
                } else {
                    List<OfflinePathBean> childPaths = new ArrayList<>();
                    childPaths.add(path);
                    overMaps.put(path.getPlan_id(), childPaths);
                }
            }
            dbDaoHelper.updateOfflinePaths(nowOverPaths);
            /*7.A:如果有任务点到位，则state=1（代表这个轨迹点是到位轨迹点）; B:如果没有到位，则state=0；*/
            if (overMaps != null && overMaps.size() > 0) {
                checkPlanIsOver(overMaps);
                EventBus.getDefault().post(new UiPlan.PlanEvent(UiPlan.PLAN_POINT_OVER, overMaps));
                gpsDataBean.setState(1);
            }else {
                gpsDataBean.setState(0);
            }
        }
    }

    /*判断已到位的点的计划，是否计划已经完成。判断依据：计划的点未到位的个数<=0*/
    private void checkPlanIsOver(Map<String, List<OfflinePathBean>> overMaps){
        if (overMaps != null && overMaps.size() > 0) {
            for (String plan_id : overMaps.keySet()) {
                PlanTool planTool = PlanTool.getInstance();
                planTool.setPlanIsOver(plan_id);
                /*增加本地上传更新完成率的工作*/
                addPlanOfflineJob(plan_id);
            }
        }
    }

    private void addPlanOfflineJob(String plan_id) {
        PlanTool planTool = PlanTool.getInstance();
        planTool.addPlanOfflineJob(plan_id);
    }


    /*计算巡检线的到位时间，判断依据：到位时间不为空而离开时间为空的到位点，比较当前的坐标点是否在容差范围
    * 外，是则表示已离开并记录离开时间*/
    private void checkOfflinePointOffTime(double lng, double lat, String speed, String check_time, int planMode) {
        final int notover = OfflinePathBean.POINTLINE_NOT_OVER;
        final int over = OfflinePathBean.POINTLINE_IS_OVER;

        /*未到点巡检线的点*/
        UserBean user = BaseApp.getInstance().getLoginUser();
        String userid = user.getUserid();
        List<OfflinePathBean> nullOffTimePaths = dbDaoHelper.getOverPathLineListForNullOffTime(userid, planMode);
        final List<OfflinePathBean> offPaths = new ArrayList<>();
        if (nullOffTimePaths != null) {
            for (OfflinePathBean path : nullOffTimePaths) {
                double x = path.getLng();
                double y = path.getLat();
                boolean isover = checkRoutePointOver(x, y, lng, lat);
                if (!isover) {
                    path.setFirst_left_time(check_time);
                    dbDaoHelper.updateOfflinePath(path);
                    offPaths.add(path);
                }
            }
            if (offPaths != null && offPaths.size() > 0) {
                if (mContext == null)
                    mContext = BaseApp.getInstance().getApplicationContext();
                if (planController == null)
                    planController = new PlanController(mContext);
                planController.updatePathOffTime(user.getToken(), offPaths, new PlanCallBack() {
                    @Override
                    public void onUpdatePathOffTime(boolean isSuccess, int errorCode, String errMsg) {
                        super.onUpdatePathOffTime(isSuccess, errorCode, errMsg);
                        if (isSuccess) {
                            for (OfflinePathBean path : offPaths) {
                                path.setIsoffupload(1);
                            }
                            dbDaoHelper.updateOfflinePaths(offPaths);
                        } else {

                        }
                    }
                });
            }
        }
    }

    private void checkBuildInPlace(GPSDataBean gpsDataBean, boolean isFloatPoint){
        double lng = Double.parseDouble(gpsDataBean.getLng());
        double lat = Double.parseDouble(gpsDataBean.getLat());
        List<BuildHandleDataBean> buildLogList = dbDaoHelper.getBuildHandleList();
        if (buildLogList != null && buildLogList.size() > 0){
            for (BuildHandleDataBean buildLog : buildLogList){
                if (buildLog != null && buildLog.getLng() > 0 && buildLog.getLat() > 0){
                    if (!isFloatPoint){
                        double x = buildLog.getLng();
                        double y = buildLog.getLat();
                        boolean isover = checkBuildPointOver(x, y, lng, lat);
                        /*超出当前工地有效范围*/
                        if (!isover){
                            sendBuildNotification(buildLog);
                            EventBus.getDefault().post(new BuildManageEvent(BuildManageEvent.BUILD_MANAGE_LOG_OVER, buildLog));
                        }else {
                            EventBus.getDefault().post(new BuildManageEvent(BuildManageEvent.BUILD_MANAGE_LOG_UPDATE_TIME, buildLog));
                        }
                    }else {
                        EventBus.getDefault().post(new BuildManageEvent(BuildManageEvent.BUILD_MANAGE_LOG_UPDATE_TIME, buildLog));
                    }
                }
            }
        }
    }

    private double getCheckScale(double tolerance) {
        double check_scale = CHECK_SCALE;
        if (!Double.isNaN(tolerance) && tolerance > 0) {
            check_scale = (double) CHECK_UNITS / tolerance;
        }
        return check_scale;
    }

    private List<OfflinePathBean> getOverPathListByPlan(String userid, double ckx, double cky) {
        List<OfflinePathBean> nowOverPaths = new ArrayList<>();

        PlanTool planTool = PlanTool.getInstance();
        List<PlanBean> localPlans = planTool.getLocalPlans();
        if (localPlans != null) {
            for (PlanBean planBean : localPlans) {
                String plan_id = planBean.getPlan_id();
                double tolerance = planBean.getTolerance();
                double check_scale = getCheckScale(tolerance);
                List<OfflinePathBean> planOverList = getNowPlanOverPathList(userid, plan_id, ckx, cky, check_scale);
                if (planOverList != null) {
                    nowOverPaths.addAll(planOverList);
                }
            }
        }

        return nowOverPaths;
    }

    private List<OfflinePathBean> getNowPlanOverPathList(String userid, String plan_id, double ckx, double cky, double check_scale){
        double xscale = D_LNG_SCALE / check_scale;
        double yscale = D_LAT_SCALE / check_scale;
        double xMin = ckx - xscale;
        double xMax = ckx + xscale;
        double yMin = cky - yscale;
        double yMax = cky + yscale;
        return dbDaoHelper.getCurrentOverPathListByPlan(userid, plan_id, xMin, xMax, yMin, yMax);
    }

    private List<OfflinePathBean> getNowOverPathList(String userid, int planMode, double ckx, double cky, double check_scale){
        double xscale = D_LNG_SCALE / check_scale;
        double yscale = D_LAT_SCALE / check_scale;
        double xMin = ckx - xscale;
        double xMax = ckx + xscale;
        double yMin = cky - yscale;
        double yMax = cky + yscale;
        return dbDaoHelper.getCurrentOverPathList(userid, planMode, xMin, xMax, yMin, yMax);
    }

    private List<OfflinePathBean> getNowOverProjectPathList(String userid, int planMode, double ckx, double cky, double check_scale){
        double xMin = ckx - check_scale;
        double xMax = ckx + check_scale;
        double yMin = cky - check_scale;
        double yMax = cky + check_scale;
        return dbDaoHelper.getCurrentOverPathList(userid, planMode, xMin, xMax, yMin, yMax);
    }

    private static boolean checkIsPointOver(double x, double y, double ckx, double cky, double check_scale) {
        double xscale = D_LNG_SCALE / check_scale;
        double yscale = D_LAT_SCALE / check_scale;
        double xMin = ckx - xscale;
        double xMax = ckx + xscale;
        double yMin = cky - yscale;
        double yMax = cky + yscale;

        boolean isOver = false;
        if (x >= xMin && x <= xMax) {
            if (y >= yMin && y <= yMax) {
                isOver = true;
            }
        }
        return isOver;
    }

    public static boolean checkRoutePointOver(double x, double y, double ckx, double cky) {
        double CHECK_SCALE = getInstance().getRouteCheckScale();
        return checkIsPointOver(x, y, ckx, cky, CHECK_SCALE);
    }

    public static boolean checkRouteDevicePointOver(double x, double y, double ckx, double cky, double tolerance) {
        double CHECK_SCALE = getInstance().getRouteCheckScaleDevice();
        if (!Double.isNaN(tolerance) && tolerance > 0) {
            CHECK_SCALE = (double) CHECK_UNITS / tolerance;
        }
        return checkIsPointOver(x, y, ckx, cky, CHECK_SCALE);
    }

    public static boolean checkRouteCarPointOver(double x, double y, double ckx, double cky) {
        double CHECK_SCALE = getInstance().getRouteCheckScaleCar();
        return checkIsPointOver(x, y, ckx, cky, CHECK_SCALE);
    }

    public static boolean checkBuildPointOver(double x, double y, double ckx, double cky) {
        double CHECK_SCALE = getInstance().getBuildCheckScale();
        return checkIsPointOver(x, y, ckx, cky, CHECK_SCALE);
    }

    @SuppressLint("NewApi")
    private void sendNotification(OfflinePathBean pathBean) {
        Intent intent = new Intent(mContext, UiPlanDetail.class);
        Bundle bundle = new Bundle();
        bundle.putString("plan_id", pathBean.getPlan_id());
        intent.putExtras(bundle);
        PendingIntent pendIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        Notification.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    mContext.getPackageName(),
                    "巡检任务(巡检系统)",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            notificationManager.createNotificationChannel(channel);
            builder = new Notification.Builder(mContext, channel.getId());
        }else {
            builder = new Notification.Builder(mContext);
        }
        builder.setContentIntent(pendIntent);
        builder.setSmallIcon(R.mipmap.logo);
        builder.setContentTitle("到位提醒");
        builder.setContentText("你有一个巡检点已到位.");
        Notification notification = builder.build();
        notification.flags = Notification.FLAG_AUTO_CANCEL;
        notification.defaults = Notification.DEFAULT_LIGHTS;
        notification.defaults |= Notification.DEFAULT_SOUND;
        notification.vibrate = new long[]{0};
        notification.flags |= Notification.FLAG_SHOW_LIGHTS;
        notificationManager.notify(DeviceInfoTool.ntfTagSchedule, notification);
    }

    @SuppressLint("NewApi")
    private void sendBuildNotification(BuildHandleDataBean buildLog) {
        Intent intent = new Intent(mContext, UiBuildManage.class);
        Bundle bundle = new Bundle();
        intent.putExtras(bundle);
        PendingIntent pendIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        Notification.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    mContext.getPackageName(),
                    "工地监护(巡检系统)",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            notificationManager.createNotificationChannel(channel);
            builder = new Notification.Builder(mContext, channel.getId());
        }else {
            builder = new Notification.Builder(mContext);
        }
        builder.setContentIntent(pendIntent);
        builder.setSmallIcon(R.mipmap.logo);
        builder.setContentTitle("工地监护结束");
        builder.setContentText("监护工地已经超出有效范围，该工地监护结束.");
        Notification notification = builder.build();
        notification.flags = Notification.FLAG_AUTO_CANCEL;
        notification.defaults = Notification.DEFAULT_ALL;
        notification.defaults |= Notification.DEFAULT_LIGHTS;
        notification.flags |= Notification.FLAG_SHOW_LIGHTS;
        int notifyId = UUID.randomUUID().variant();
        notificationManager.notify(notifyId, notification);
    }

    @SuppressLint("MissingPermission")
    private final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
        @Override
        public void onGpsStatusChanged(int event) {
            GpsStatus status = mLocationManager.getGpsStatus(null); // 取当前状态
            updateGpsStatus(event, status);
        }
    };

    @SuppressLint("MissingPermission")
    public void refreshLocationManager() {
        if (gpsSatelliteList.size() != 0 && mLocation != null && mLocation.getProvider().equals(GPS_PROVIDER)){
            return;
        }

        if (mLocation == null || PROVIDER.equals(NETWORK_PROVIDER)) {
            if (PROVIDER.equals(GPS_PROVIDER)) {
                gps_no_result++;
            }
            if (gps_no_result >= 1) {
                PROVIDER = NETWORK_PROVIDER;
            }

            if (PROVIDER.equals(NETWORK_PROVIDER)) {
                Location lastLoc = mLocationManager.getLastKnownLocation(GPS_PROVIDER);
                if (lastLoc != null) {
                    PROVIDER = GPS_PROVIDER;
                }else {
                    mLocationManager.requestLocationUpdates(GPS_PROVIDER, LOC_TIME, LOC_DISTANCE, gpsListener, Looper.getMainLooper());
                }
            }
        } else {
            gps_no_result = 0;
        }

        mLocationManager.requestLocationUpdates(PROVIDER, LOC_TIME, LOC_DISTANCE, locationListener, Looper.getMainLooper());
    }

    public Location getLocationInfo() {
        /*Location lastLoc = mLocationManager.getLastKnownLocation(PROVIDER);
        if (lastLoc != null) {
            mLocation = lastLoc;
        }*/
        return mLocation;
    }

    public GPSDataBean getLastLocation() {
        return  mLastLocation;
    }

    public boolean isLastLocationValid() {
        return isGpsValid;
    }

    public boolean isLocationServiceRunning() {
        //return isRunning;
        return AmapLocationUtils.getInstance().isServiceRunning();
    }

    private void updateGpsStatus(int event, GpsStatus status) {
        if (status == null)
            return;

        if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {
            int maxSatellites = status.getMaxSatellites();
            Iterator<GpsSatellite> it = status.getSatellites().iterator();
            gpsSatelliteList.clear();
            int count = 0;
            while (it.hasNext() && count <= maxSatellites) {
                GpsSatellite s = it.next();
                if (s.usedInFix()){
                    gpsSatelliteList.add(s);
                    count++;
                }
            }
        }
    }
}
