package com.tofly.ghrq_route.module.deviceInfo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.PowerManager;

import com.mgq.base.utils.logger.LogRecorder;
import com.mgq.base.utils.string.StringUtil;
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.C;
import com.tofly.ghrq_route.base.MultiAsyncTask;
import com.tofly.ghrq_route.base.url.NetRequestURL;
import com.tofly.ghrq_route.base.URLResponseCode;
import com.tofly.ghrq_route.module.OfflineWork.OfflineWorkTool;
import com.tofly.ghrq_route.module.deviceInfo.controller.DeviceInfoCallback;
import com.tofly.ghrq_route.module.deviceInfo.controller.DeviceInfoController;
import com.tofly.ghrq_route.module.deviceInfo.domain.DeviceInfoBean;
import com.tofly.ghrq_route.module.gps.GpsTool;
import com.tofly.ghrq_route.module.gps.domain.GPSDataBean;
import com.tofly.ghrq_route.module.job.JobTool;
import com.tofly.ghrq_route.module.job.controller.JobCallBack;
import com.tofly.ghrq_route.module.job.domain.MyJobEvent;
import com.tofly.ghrq_route.module.message.MessageTool;
import com.tofly.ghrq_route.module.message.controller.MessageCallBack;
import com.tofly.ghrq_route.module.message.controller.MessageController;
import com.tofly.ghrq_route.module.message.domain.InMessageBean;
import com.tofly.ghrq_route.module.notifyManage.NotifyManageBean;
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.ChildPlanCountBean;
import com.tofly.ghrq_route.module.plan.domain.OfflinePathBean;
import com.tofly.ghrq_route.module.plan.domain.PlanBean;
import com.tofly.ghrq_route.module.sign.domain.SignDataBean;
import com.tofly.ghrq_route.module.sqlite.DBDaoHelper;
import com.tofly.ghrq_route.module.systemConfig.SystemConfigTool;
import com.tofly.ghrq_route.module.systemConfig.controller.ServerSysConfigCallBack;
import com.tofly.ghrq_route.module.user.domain.UserBean;
import com.tofly.ghrq_route.common.ui.activity.HomeActivity;
import com.tofly.ghrq_route.common.ui.activity.UiJobList;
import com.tofly.ghrq_route.common.ui.activity.UiPlan;
import com.tofly.ghrq_route.common.util.EventBusUtil;
import com.tofly.ghrq_route.common.util.Notification.NotificationUtil;
import com.tofly.ghrq_route.common.util.date.DateUtils;
import com.tofly.ghrq_route.common.util.file.FileUtil;
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.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import static com.tofly.ghrq_route.base.C.UPLOAD_SAVED_LIMIT_COUNT;
import static com.tofly.ghrq_route.common.util.net.NetUtil.NETWORN_NONE;

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

public class DeviceInfoTool {

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

    private static DeviceInfoTool deviceInfoTool = null;

    private DeviceInfoController deviceInfoController;

    private MessageController messageController;

    private PlanController planController;

    private BatteryInfoReceiver batteryInfoReceiver;

    private GpsTool gpsTool;

    private PlanTool planTool;

    private DBDaoHelper dbDaoHelper;

    private Context mContext;

    private PowerManager powerManager;

    private PowerManager.WakeLock wakeLock;

    private int mBatteryHealth = 0;

    private int mUnreadMessageCount = 0;

    private NotificationManager notificationManager = null;

    private int pageindex = 1;
    private final int pagesize = C.DEFAULT_MAX_LOAD_PAGESIZE;

    public static final int ntfTagMessage = 1001;
    public static final int ntfTagNormal = 1002;
    public static final int ntfTagSchedule = 1003;
    public static final int ntfTagPlan = 1004;
    public static final int ntfTagPlanErr = 1005;
    public static final int ntfTagBackupServer = 1006;
    public static final int ntfTagJob = 1007;

    private static int mConnectResCode = 0;

    private static final int MAX_CHECK_PLAN_TIMES = 5;

    private static int mUploadCheckPlanTimes = 0;

    public static final int MAX_PLAN_POINT_DOWN_ERR_TIMES = 3;

    private boolean bCheckTodayPlanCountIng = false;

    public static final int POINT_DOWN_PAGE_SIZE = C.DEFAULT_MAX_LOAD_PAGESIZE;

    private DeviceInfoTool(){
        gpsTool = GpsTool.getInstance();
        planTool = PlanTool.getInstance();
        dbDaoHelper = DBDaoHelper.getInstance();
        powerManager = (PowerManager) BaseApp.getInstance().getSystemService(Context.POWER_SERVICE);
        notificationManager = (NotificationManager) BaseApp.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
    }

    public static synchronized DeviceInfoTool getInstance(){
        if (deviceInfoTool == null){
            deviceInfoTool = new DeviceInfoTool();
        }
        return deviceInfoTool;
    }

    public int getGpsStar() {
        int gpsStar = 0;
        if (gpsTool != null){
            GPSDataBean gpsDataBean = gpsTool.getLastLocation();
            if (gpsDataBean != null) {
                gpsStar = gpsDataBean.getGps_star();
            }
        }
        return gpsStar;
    }

    public int getBatteryHealth(){
        return mBatteryHealth;
    }

    public void startChecking(Context context){
        mContext = context;

        if (null == wakeLock) {
            wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "route:track_upload");
        }
        batteryInfoReceiver = new BatteryInfoReceiver(wakeLock);
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_USER_PRESENT);
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiver(batteryInfoReceiver, filter);

        //gpsTool.observeGpsStar();

        mBatteryHealth = BaseApp.getInstance().getBatteryUsage();

        mUploadCheckPlanTimes = 0;

        checkDeviceInfo(DeviceInfoBean.WORK_STATE_ING);
    }

    public void stopChecking(){
        if (mContext != null && batteryInfoReceiver != null)
            mContext.unregisterReceiver(batteryInfoReceiver);

        //gpsTool.stopObserveGpsStar();
    }

    public void checkDeviceInfo(int workState){
        boolean isNetConnected = BaseApp.isNetworkConnected();
        DeviceInfoBean deviceInfoBean = getDeviceInfo();
        if (deviceInfoBean.getElectricity() > 0){
            if (isNetConnected) {
                mUploadCheckPlanTimes++;
                //上传GPS数据
                uploadDeviceInfo(deviceInfoBean, workState);
                checkSavedDeviceInfo();
                checkMessage();
                checkUnhandledJob();
                if (mUploadCheckPlanTimes >= MAX_CHECK_PLAN_TIMES){
                    checkTodayPlanCount(true, null);
                }
            }else {
                saveDeviceInfo(deviceInfoBean);
                mConnectResCode = URLResponseCode.ErrorCode.NETWORK_ERROR;
                EventBus.getDefault().post(new DeviceInfoToolEvent(DEVICEINFO_CONNECTION_INFO, mConnectResCode));
            }
        }
        if (mUploadCheckPlanTimes >= MAX_CHECK_PLAN_TIMES){
            mUploadCheckPlanTimes = 0;
        }
    }

    public DeviceInfoBean getDeviceInfo(){
        DeviceInfoBean deviceInfoBean = new DeviceInfoBean();

        String deviceInfoId = UUID.randomUUID().toString();
        deviceInfoBean.setId(deviceInfoId);

        /*电量*/
        if (mBatteryHealth == 0){
            mBatteryHealth = BaseApp.getInstance().getBatteryUsage();
        }
        deviceInfoBean.setElectricity(mBatteryHealth);

        /*网络连接状态*/
        int networkState = NetUtil.getNetworkState(BaseApp.getInstance());
        deviceInfoBean.setNetwork_state(networkState != NETWORN_NONE ? 1 : 0);
        /*网络连接类型*/
        if (networkState != NETWORN_NONE){
            deviceInfoBean.setNetwork_type(networkState);
        }

        /*GPS开关状态*/
        boolean isGpsOpen = gpsTool.isGpsOpen();
        int gpsState = isGpsOpen ? 1 : 0;
        if (isGpsOpen){
            if (gpsTool.isLocationServiceRunning()){
                boolean isLocationValid = gpsTool.isLastLocationValid();
                if (!isLocationValid){
                    gpsState = 2;
                }
            }
        }
        deviceInfoBean.setGps_state(gpsState);

        /*GPS卫星可数*/
        GPSDataBean gpsDataBean = gpsTool.getLastLocation();
        if (gpsDataBean != null) {
            /*GPS精度*/
            deviceInfoBean.setGps_precision(gpsDataBean.getGps_precision());
            deviceInfoBean.setGps_star(gpsDataBean.getGps_star());
        }

        /*监测数据时间*/
        String time = DateUtils.getDate(new Date().getTime());
        deviceInfoBean.setCheck_time(time);

        /*手机剩余空间*/
        int freeSpace = FileUtil.getFreeSpace(); //单位mb
        deviceInfoBean.setResidual_space(String.valueOf(freeSpace));

        UserBean userBean = BaseApp.getInstance().getLoginUser();
        int carMode = BaseApp.getInstance().isCarMode() ?
                UserBean.PATROL_TYPE_CAR : UserBean.PATROL_TYPE_WALK;
        String carid = BaseApp.getInstance().getCarNo();
        if (userBean != null){
            carMode = userBean.getCar_mode();
            carid = userBean.getCarid();
        }
        deviceInfoBean.setGps_type(carMode);
        deviceInfoBean.setCarid(carid);

        return deviceInfoBean;
    }

    private void uploadDeviceInfo(final DeviceInfoBean deviceInfoBean, int workState){
        UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (userBean != null){
            if (mContext == null)
                mContext = BaseApp.getInstance().getApplicationContext();
            if (deviceInfoController == null)
                deviceInfoController = new DeviceInfoController(mContext);
            deviceInfoController.uploadDeviceInfo(userBean.getToken(), userBean.getUserid(), deviceInfoBean, workState, new DeviceInfoCallback(){
                @Override
                public void onUploadDeviceInfo(boolean isSuccess, int errorCode, String errMsg, int section) {
                    super.onUploadDeviceInfo(isSuccess, errorCode, errMsg, section);
                    if (isSuccess){
                        if (section > 0){
                            GpsTool.getInstance().setGpsDataSection(section);
                        }
                    }else {
                        saveDeviceInfo(deviceInfoBean);
                    }
                    mConnectResCode = errorCode;
                    EventBus.getDefault().post(new DeviceInfoToolEvent(DEVICEINFO_CONNECTION_INFO, mConnectResCode));
                }
            });
        }
    }

    private void saveDeviceInfo(DeviceInfoBean deviceInfoBean){
        dbDaoHelper.insertOrUpdateDeviceInfo(deviceInfoBean);
    }

    private void checkSavedDeviceInfo(){
        if (C.is_passed_notify)
            return;

        final List<DeviceInfoBean> savedDeviceInfoList = dbDaoHelper.getSavedDeviceInfoList(UPLOAD_SAVED_LIMIT_COUNT);
        UserBean user = BaseApp.getInstance().getLoginUser();
        if (user != null){
            if (savedDeviceInfoList != null && savedDeviceInfoList.size() > 0){
                if (mContext == null)
                    mContext = BaseApp.getInstance().getApplicationContext();
                if (deviceInfoController == null)
                    deviceInfoController = new DeviceInfoController(mContext);
                deviceInfoController.uploadBatchDeviceInfo(user.getToken(), user.getUserid(), savedDeviceInfoList, new DeviceInfoCallback(){
                    @Override
                    public void onUploadBatchDeviceInfo(boolean isSuccess, int errorCode, String errMsg) {
                        super.onUploadBatchDeviceInfo(isSuccess, errorCode, errMsg);
                        if (isSuccess){
                            dbDaoHelper.deleteSavedDeviceInfo(savedDeviceInfoList);
                        }
                    }
                });
            }
        }
    }

    public void checkMessage(){
        UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (mContext == null)
            mContext = BaseApp.getInstance().getApplicationContext();
        if (messageController == null)
            messageController = new MessageController(mContext);
        if (userBean != null){
            messageController.getRecvMsgList(userBean.getToken(), 0,  pageindex, pagesize, new MessageCallBack(){
                @Override
                public void onGetRecvMsgList(boolean isSuccess, int errorCode, String errMsg, List<InMessageBean> messageList, int total) {
                    super.onGetRecvMsgList(isSuccess, errorCode, errMsg, messageList, total);
                    if (isSuccess && messageList != null){
                            Iterator<InMessageBean> it = messageList.iterator();
                            while (it.hasNext()) {
                                InMessageBean a = it.next();
                                if (!a.getFlag().equals("0")) {
                                    it.remove();
                                }
                            }
                        mUnreadMessageCount = messageList.size();
                        if (mUnreadMessageCount > 0){
                            saveUnNotifyMessage(messageList);
                            sendNotificationMessage();
                        }
                        EventBus.getDefault().post(new DeviceInfoToolEvent(DEVICEINFO_UNREAD_MESSAGE, messageList));
                    }else {

                    }
                }
            });
        }
    }

    public void checkUnhandledJob() {
        JobTool jobTool = JobTool.getInstance();
        if (mContext == null)
            mContext = BaseApp.getInstance().getApplicationContext();
        jobTool.getServerUnhandledJob(mContext, new JobCallBack(){
            @Override
            public void onGetUnHandledJobCount(boolean isSuccess, int errorCode, String errMsg, List<String> jobIds, int count) {
                super.onGetUnHandledJobCount(isSuccess, errorCode, errMsg, jobIds, count);
                if (jobIds != null && jobIds.size() > 0) {
                    List<NotifyManageBean> unNotifyMsgBeans = jobTool.getUnNotifyMsgBean();
                    if (unNotifyMsgBeans != null && unNotifyMsgBeans.size() > 0) {
                        EventBusUtil.postEvent(new MyJobEvent(MyJobEvent.MY_JOB_LIST_NEW_JOB));
                        sendNotificationJob();
                        jobTool.setMsgBeanNotified(unNotifyMsgBeans);
                    }
                }
            }
        });
    }

    public interface CheckTodayPlanCountCallback{
        void GetTodayPlanCount(int retCode, String errMsg, boolean bAlertNew, int count);
    }

    public boolean isChedingTodayPlanCount(){
        return bCheckTodayPlanCountIng;
    }

    public void checkTodayPlanCount(final boolean bAlertNew, final CheckTodayPlanCountCallback callback){
        bCheckTodayPlanCountIng = true;
        final UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (userBean == null){
            if (callback != null)
                callback.GetTodayPlanCount(-1, "用户数据为空", false, 0);
            EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
            bCheckTodayPlanCountIng = false;
            return;
        }

        SignDataBean signDataBean = dbDaoHelper.getTodaySignOn();
        /*正在下载中*/
        if (signDataBean != null ){
            /*是否正在下载中*/
            boolean isDownloading = signDataBean.getPlanState() == SignDataBean.PLAN_DOWNLOADING_STATE;
            /*是否刚刚提示过有更新*/
            boolean isUpadte = userBean.isCarMode() ?
                    (signDataBean.getCarNeedUpdate() == 1) : (signDataBean.getNeedUpdate() == 1);

            String logMsg = String.format("DeviceInfoToll ：checkTodayPlan 是否正在更新 ---signData.getPlanState:%d needUpdate:%s \n", signDataBean.getPlanState(), String.valueOf(isUpadte));
            LogRecorder.writeDeviceToolLog(mContext, logMsg, userBean.getUserid());

            if (isDownloading || isUpadte){
                if (callback != null)
                    callback.GetTodayPlanCount(-2, "正在有任务在下载中，请稍后再试",false, 0);
                EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
                bCheckTodayPlanCountIng = false;
                return;
            }
        }
        if (mContext == null)
            mContext = BaseApp.getInstance().getApplicationContext();
        if (planController == null)
            planController = new PlanController(mContext);
        final int carmode = userBean.isCarMode() ? 1 : 0;
        final String userid = userBean.getUserid();
        List<String> localPlanIds = dbDaoHelper.getOfflinePathPlanIds(userid, carmode);
        if (userBean != null){
            /*日志记录*/
            String strPlanIds = StringUtil.listToString(localPlanIds, ',');
            String logMsg = String.format("查询当前本地已下载的计划Id：%s \n", strPlanIds);
            LogRecorder.writeDeviceToolLog(mContext, logMsg, userid);
            logMsg = String.format("开始查取服务器计划个数 用户:%s 车讯模式:%d \n", userid, carmode);
            LogRecorder.writeDeviceToolLog(mContext, logMsg, userid);

            planController.getTodayPlanCount(mContext, userid, carmode, localPlanIds, new PlanCallBack(){
                @Override
                public void onGetTodayPlanCount(boolean isSuccess, int errorCode, String errMsg, int count, List<ChildPlanCountBean> planIdCounts) {
                    super.onGetTodayPlanCount(isSuccess, errorCode, errMsg, count, planIdCounts);
                    if (isSuccess){
                        SignDataBean onSign = dbDaoHelper.getTodaySignOn();
                        if (onSign == null){
                            onSign = new SignDataBean();
                            onSign.setPlanDate(DateUtils.getYMD());
                            onSign.setPlanState(1);
                            dbDaoHelper.insertOrUpdateSignOn(onSign);
                        }
                        if (onSign != null && planIdCounts != null){
                            /*保存当天所需要下载的计划*/
                            SharePreUtil.setPlanPointTodayPlan(planIdCounts);
                            /*判断是否需要下载离线点*/
                            boolean isNewPlan[] = {false};
                            List<String> updatePlanList = checkLocalPlanNeedUpdate(planIdCounts, isNewPlan, userid);
                            boolean bShouleAlertNew = isNewPlan[0] && bAlertNew;
                            int retCode = -1;
                            int recCount = updatePlanList.size();
                            if (carmode == UserBean.PATROL_TYPE_WALK){
                                if (updatePlanList != null){
                                    if (updatePlanList.size() > 0){
                                        retCode = 0;
                                        onSign.setNeedUpdate(1);
                                        onSign.setPlanNum(count);
                                        String strPlanIds = StringUtil.listToString(updatePlanList, ',');
                                        onSign.setPlanIds(strPlanIds);
                                        dbDaoHelper.insertOrUpdateSignOn(onSign);
                                        sendNotificationPlan();
                                        if (callback == null)
                                            EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_TODAY_PLAN_CHANGED, bShouleAlertNew));
                                        EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
                                        bCheckTodayPlanCountIng = false;
                                    }else {
                                        retCode = 1;
                                        onSign.setNeedUpdate(0);
                                        onSign.setPlanNum(0);
                                        onSign.setPlanIds("");
                                        dbDaoHelper.insertOrUpdateSignOn(onSign);
                                        if (callback == null)
                                            EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_TODAY_NO_PLAN, null));
                                        EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
                                        bCheckTodayPlanCountIng = false;
                                    }
                                }
                            }else if (carmode == UserBean.PATROL_TYPE_CAR){
                                if (updatePlanList != null){
                                    if (updatePlanList.size() > 0){
                                        retCode = 0;
                                        onSign.setCarNeedUpdate(1);
                                        onSign.setCarPlanNum(count);
                                        String strPlanIds = StringUtil.listToString(updatePlanList, ',');
                                        onSign.setPlanIds(strPlanIds);
                                        dbDaoHelper.insertOrUpdateSignOn(onSign);
                                        sendNotificationPlan();
                                        if (callback == null)
                                            EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_TODAY_PLAN_CHANGED, bShouleAlertNew));
                                        EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
                                        bCheckTodayPlanCountIng = false;
                                    }else {
                                        retCode = 1;
                                        onSign.setCarNeedUpdate(0);
                                        onSign.setCarPlanNum(0);
                                        onSign.setPlanIds("");
                                        dbDaoHelper.insertOrUpdateSignOn(onSign);
                                        if (callback == null)
                                            EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_TODAY_NO_PLAN, null));
                                        EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
                                        bCheckTodayPlanCountIng = false;
                                    }
                                }
                            }
                            if (callback != null)
                                callback.GetTodayPlanCount(retCode, errMsg, bShouleAlertNew, recCount);
                        }else {
                            if (callback != null)
                                callback.GetTodayPlanCount(-3, "服务器返回计划的个数为空", false, 0);
                            EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
                            bCheckTodayPlanCountIng = false;
                        }
                    }else {
                        if (callback != null)
                            callback.GetTodayPlanCount(-4, errMsg, false, 0);
                        EventBus.getDefault().post(new DeviceInfoToolEvent(DeviceInfoTool.DEVICEINFO_CHECK_TODAY_PLAN_FINISHED, false));
                        bCheckTodayPlanCountIng = false;
                    }
                }
            });
        }
        mUploadCheckPlanTimes = 0;
    }

    private List<String> checkLocalPlanNeedUpdate(List<ChildPlanCountBean> serverPlanCounts, boolean isNew[], String userid){
        List<String> updateCountList = new ArrayList<>();

        boolean isNeedUploadLog = false;

        boolean isNewPlan = isNew[0];
        String logMsg = String.format("本地计划个数和离线点个数同服务器个数比较: \n");
        LogRecorder.writeDeviceToolLog(mContext, logMsg, userid);

        String planUpdateMsg = "需要下载的计划：";
        String updateMsg = "";
        for (ChildPlanCountBean countBean : serverPlanCounts){
            boolean isPointNotDownAll = false; /*点未下载全*/
            boolean isPlanNotDown = false;  /*某个计划未下载*/
            boolean isNeedDown = true;
            String countPlanId = countBean.getPlan_id();
            int countCounts = countBean.getCount();
            long localCounts = dbDaoHelper.getOfflinePathPlanCounts(countPlanId);

            long down_times = getPlanDownTimes(countPlanId);
            logMsg = String.format("计划id: %s 服务器点个数:%d 本地离线点个数: %d 已下载次数: %d \n", countPlanId, countCounts, localCounts, down_times);
            LogRecorder.writeDeviceToolLog(mContext, logMsg, userid);

            if (countCounts > localCounts){
                updateCountList.add(countPlanId);
                setPlanDownTimes(countPlanId);

                /*该计划下载不全*/
                if (localCounts > 0){
                    isPointNotDownAll = true;
                    String msg = String.format("计划id: %s 此计划下载数据不全。", countPlanId);
                    LogRecorder.writeDeviceToolLog(mContext, msg, userid);
                }

                /*该计划之前下载过*/
                down_times = getPlanDownTimes(countPlanId);
                if (down_times > 1){
                    isPlanNotDown = true;
                    if (down_times > MAX_PLAN_POINT_DOWN_ERR_TIMES){
                        isNeedDown = false;
                        updateCountList.remove(countPlanId);
                        String msg = String.format("计划id: %s 当前下载次数:%d 已经超过最大下载次数 %d, 此计划不再下载 \n", countPlanId, down_times, MAX_PLAN_POINT_DOWN_ERR_TIMES);
                        LogRecorder.writeDeviceToolLog(mContext, msg, userid);
                    }
                }else {
                    isNewPlan = true;
                }

                /*该计划需要下载，则记录到需要下载的计划日志里*/
                if (isNeedDown){
                    updateMsg = " id: " + countPlanId + ", 个数: " + countCounts + ", ";
                    planUpdateMsg += updateMsg;
                }

                /*如果此计划之前已经下载过未下载下来，或者之前下载的不全，则需要上传本地日志*/
                if (isPointNotDownAll || isPlanNotDown){
                    isNeedUploadLog = true;
                }
            }
        }
        planUpdateMsg += "\n";
        LogRecorder.writeDeviceToolLog(mContext, planUpdateMsg, userid);

        if (isNeedUploadLog){
            long err_times = SharePreUtil.getPlanPointDownErrTimes() + 1;
            SharePreUtil.setPlanPointDownErrTimes(err_times);

            /*当天下载错误次数已超过最大出错次数*/
            if (err_times >= MAX_PLAN_POINT_DOWN_ERR_TIMES){
                //sendNotificationPlanDownErrMax();
                //EventBus.getDefault().post(new DeviceInfoToolEvent(DEVICEINFO_PLAN_DOWN_ERR_MAX, null));
            }else {
                uploadPlanPointLog();
            }
        }
        NetRequestURL.isGetPlanPointNeedLog = isNeedUploadLog;

        isNew[0] = isNewPlan;
        return updateCountList;
    }

    private long getPlanDownTimes(String planId){
        long time = SharePreUtil.getPlanPointPlanDownTimes(planId);
        return time;
    }

    private void setPlanDownTimes(String planId){
        long time = SharePreUtil.getPlanPointPlanDownTimes(planId) + 1;
        SharePreUtil.setPlanPointPlanDownTimes(planId, time);
    }

    private void uploadPlanPointLog(){
        if (mContext == null)
            mContext = BaseApp.getInstance().getApplicationContext();

        UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (userBean == null)
            return;

        final String userid = userBean.getUserid();
        final String path = LogRecorder.getDeviceLogPath(mContext, userid);
        File file = new File(path);
        if (!file.exists())
            return;

        String msg = String.format("开始上传巡检点下载日志文件，路径: %s", path);
        LogRecorder.writeDeviceToolLog(mContext, msg, userid);

        List<String> files = new ArrayList<>();
        files.add(path);
        SystemConfigTool systemConfigTool = SystemConfigTool.getInstance();
        systemConfigTool.uploadLocalSystemLogFiles(mContext, files, new ServerSysConfigCallBack(){
            @Override
            public void onUploadLocalSystemLogFiles(boolean isSuccess, int errorCode, String errMsg) {
                super.onUploadLocalSystemLogFiles(isSuccess, errorCode, errMsg);

                String msg = String.format("上传巡检点下载日志文件，路径: %s, 成功: %d, 错误code: %d, 错误消息: %s",
                        path, isSuccess ? 1 : 0, errorCode, errMsg);
                LogRecorder.writeDeviceToolLog(mContext, msg, userid);
            }
        });
    }

    private final int PLAN_POINT_DOWN_TIME_OUT = 5 * 60 * 1000;
    public boolean checkTodayPlan() {
        UserBean user = BaseApp.getInstance().getLoginUser();
        if (user == null)
            return true;

        final String userid = user.getUserid();
        final int car_mode = user.getCar_mode();
        boolean hasSignPlan = true;
        SignDataBean signData = dbDaoHelper.getTodaySignOn();
        if (signData != null && signData.getPlanState() == 0) {
            final String listPlanIds = signData.getPlanIds();

            String logMsg = String.format("离线点下载 需要下载的计划Id：");
            if (listPlanIds == null || listPlanIds.isEmpty()) {
                LogRecorder.writeDeviceToolLog(mContext, logMsg, userid);
                return true;
            }

            LogRecorder.writeDeviceToolLog(mContext, listPlanIds, userid);

            /*设置正在下载中*/
            signData.setPlanState(2);
            dbDaoHelper.insertOrUpdateSignOn(signData);

            logMsg = String.format("开始下载离线点： 设置正在下载中---signData.setPlanState(2); \n");
            LogRecorder.writeDeviceToolLog(mContext, logMsg, userid);

            final SignDataBean finalSignData = signData;
            MultiAsyncTask planPointMultiTask = new MultiAsyncTask(MultiAsyncTask.InvokeMode.SYNC, new MultiAsyncTask.OnTasksFinishListener() {
                @Override
                public void onFinish() {
                    setSignPlanData(finalSignData, true, car_mode);
                    planTool.checkLocalPlanIsOver();
                    EventBus.getDefault().post(new UiPlan.PlanEvent(UiPlan.PLAN_POINT_DOWNLOAD_FINISHED, true));
                    OfflineWorkTool.getInstance().resetPlanBuildWork(mContext);
                }

                @Override
                public void onTimeOut() {
                    setSignPlanData(finalSignData, false, car_mode);
                    ToastUtil.showToast(mContext, "下载巡检计划超时");
                    EventBus.getDefault().post(new UiPlan.PlanEvent(UiPlan.PLAN_POINT_DOWNLOAD_FINISHED, false));
                }
            });
            planPointMultiTask.setTimeOut(PLAN_POINT_DOWN_TIME_OUT);
            String planIds[] = listPlanIds.split(",");
            boolean hasTask = false;
            for (int i = 0; i < planIds.length; i++) {
                String planId = planIds[i];
                if (planId != null && !planId.isEmpty()) {
                    hasTask = true;
                    List<Integer> pageIndexes = checkPointPageindex(planId);
                    for (Integer pageIndex : pageIndexes) {
                        DownPlanPointTask pointTask = new DownPlanPointTask(planId, user, planPointMultiTask, pageIndex, pageIndexes, i+1, planIds.length);
                        planPointMultiTask.addTask(pointTask);
                    }
                }
            }
            if (hasTask) {
                EventBus.getDefault().post(new UiPlan.PlanEvent(UiPlan.PLAN_POINT_DOWNLOAD_STARTED, planIds.length));
                planPointMultiTask.execute();
            }
            else {
                setSignPlanData(finalSignData, false, car_mode);
                return true;
            }
        } else {
            long count = dbDaoHelper.getLocalPathSize(user.getUserid(), car_mode);
            hasSignPlan =  count > 0;
        }
        return hasSignPlan;
    }

    private List<Integer> checkPointPageindex(String planId) {
        List<Integer> pageIndexes = new ArrayList<>();
        PlanBean planBean = planTool.getLocalPlan(planId);
        if (planBean == null)
            return pageIndexes;

        int point_num = planBean.getPoint_num();
        int pages = point_num / POINT_DOWN_PAGE_SIZE + 1;
        for (int page = 1; page <= pages; page++) {
            long localPageCounts = planTool.getOfflinePathPlanCounts(planId, page);
            int serverPageCounts;
            if (page < pages) {
                serverPageCounts = POINT_DOWN_PAGE_SIZE;
            } else {
                serverPageCounts = point_num % POINT_DOWN_PAGE_SIZE;
            }
            if (localPageCounts != serverPageCounts) {
                pageIndexes.add(page);
            }
        }
        return pageIndexes;
    }

    class DownPlanPointTask extends MultiAsyncTask.AsyncTask {
        UserBean user;
        String planId;
        int current;
        int total;
        MultiAsyncTask multiAsyncTask;
        int pageindex;
        List<Integer> indexes;
        public DownPlanPointTask(String planId, UserBean user, MultiAsyncTask task, int pageindex, List<Integer> indexes, int current, int total) {
            this.planId = planId;
            this.user = user;
            this.multiAsyncTask = task;
            this.pageindex = pageindex;
            this.indexes = indexes;
            this.current = current;
            this.total = total;
        }
        @Override
        public void taskRun() {
            if (mContext == null)
                mContext = BaseApp.getInstance().getApplicationContext();

            if (planController == null)
                planController = new PlanController(mContext);
            planController.getOfflinePathListByPage(user.getToken(), user.getUserid(), planId, pageindex, POINT_DOWN_PAGE_SIZE, new PlanCallBack() {
                @Override
                public void onGetOfflinePathList(boolean isSuccess, int errorCode, String errMsg, List<OfflinePathBean> offlinePathList) {
                    super.onGetOfflinePathList(isSuccess, errorCode, errMsg, offlinePathList);
                    if (isSuccess) {
                        if (offlinePathList != null && offlinePathList.size() >= 0) {
                            setPlanDownloadTime(planId);
                            saveOfflinePathPoint(offlinePathList, pageindex);
                        }
                    }else {
                        ToastUtil.showToast(mContext, errMsg);
                    }
                    finishTask();
                }
            });
            int index = indexes.indexOf(pageindex);
            int progress = (int)((float) (index + 1) / indexes.size() * 100);
            EventBus.getDefault().post(new UiPlan.PlanEvent(UiPlan.PLAN_POINT_DOWNLOAD_CURRENT, current, total, progress));
        }
    }

    private void setSignPlanData(SignDataBean onSign, boolean hasPlan, int car_mode) {
        if (onSign == null) {
            onSign = new SignDataBean();
            String todayDate = DateUtils.getYMD();
            onSign.setPlanDate(todayDate);
            onSign.setPlanState(1);
            if (car_mode == UserBean.PATROL_TYPE_CAR)
                onSign.setCarNeedUpdate(0);
            else
                onSign.setNeedUpdate(0);
            onSign.setHasPlan(hasPlan ? 1 : 0);
            dbDaoHelper.insertOrUpdateSignOn(onSign);
        } else {
            SignDataBean signOnData = dbDaoHelper.getTodaySignOn();
            if (signOnData != null) {
                signOnData.setPlanState(1);
                signOnData.setHasPlan(hasPlan ? 1 : 0);
                if (car_mode == UserBean.PATROL_TYPE_CAR)
                    signOnData.setCarNeedUpdate(0);
                else
                    signOnData.setNeedUpdate(0);
                dbDaoHelper.insertOrUpdateSignOn(signOnData);
            }
        }
    }

    private void saveOfflinePathPoint(final List<OfflinePathBean> offlinePathList, int pageindex) {
            UserBean userBean = BaseApp.getInstance().getLoginUser();
            if (userBean != null){
                String userid = userBean.getUserid();
                dbDaoHelper.insertOfflinePathListWithAll(userid, offlinePathList, pageindex);
            }
    }

    private void setPlanDownloadTime(String planIds){
        if (planIds != null && !planIds.isEmpty()){
            String[] listPlanIds = planIds.split(",");
            if (listPlanIds != null && listPlanIds.length > 0){
                for (String planId : listPlanIds){
                    PlanBean planBean = dbDaoHelper.getPlan(planId);
                    if (planBean != null){
                        planBean.setDownload_time(DateUtils.getDate());
                        dbDaoHelper.insertOrUpdatePlan(planBean);
                    }
                }
            }
        }
    }

    private void saveUnNotifyMessage(List<InMessageBean> messageList) {
        MessageTool messageTool = MessageTool.getInstance();
        messageTool.saveUnNotifyMessage(messageList);
    }

    private void prepareSendNotification() {
        boolean enabled = NotificationUtil.isNotificationEnabled(mContext);
        boolean hasAlertOff = BaseApp.isHasAlertNoticeOff();
        if (!enabled && !hasAlertOff) {
            Activity activity = BaseApp.getInstance().currentActivity();
            if (activity != null) {
                NotificationUtil.showPermissionDialog(activity);
                BaseApp.setHasAlertNoticeOff(true);
            }
        }
    }

    private void sendNotificationMessage(){
        prepareSendNotification();

        Intent intent = new Intent(mContext, HomeActivity.class);
        Bundle bundle = new Bundle();
        bundle.putInt(HomeActivity.INDEX_HOME_ACTIVITY_KEY, R.id.radio_btn_message);
        intent.putExtras(bundle);
        PendingIntent pendIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        String channelName = "新信息(巡检系统)";
        String title = "新信息";
        String message = "你有一条新的消息，请查看。";
        Notification notification = NotificationUtil.createNotification(mContext,
                channelName, pendIntent, title, message);
        notificationManager.notify(ntfTagMessage, notification);
    }

    private void sendNotificationJob(){
        prepareSendNotification();

        Intent intent = new Intent(mContext, UiJobList.class);
        PendingIntent pendIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        String channelName = "我的工单(巡检系统)";
        String title = "我的工单";
        String message = "你有一条新的工单，请查看。";
        Notification notification = NotificationUtil.createNotification(mContext,
                channelName, pendIntent, title, message);
        notificationManager.notify(ntfTagJob, notification);
    }

    private void sendNotificationPlan(){
        prepareSendNotification();

        Intent intent = new Intent(mContext, UiPlan.class);
        PendingIntent pendIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        String channelName = "巡检任务(巡检系统)";
        String title = "新的巡检任务";
        String message = "你今天有新的巡检计划，请点击查看。";
        Notification notification = NotificationUtil.createNotification(mContext,
                channelName, pendIntent, title, message);
        notificationManager.notify(ntfTagPlan, notification);
    }

    private void sendNotificationPlanDownErrMax(){
        prepareSendNotification();

        Intent intent = new Intent(mContext, HomeActivity.class);
        Bundle bundle = new Bundle();
        bundle.putBoolean(DEVICEINFO_PLAN_DOWN_ERR_MAX, true);
        intent.putExtras(bundle);
        PendingIntent pendIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        String channelName = "巡检任务(巡检系统)";
        String title = "巡检任务下载失败";
        String message = "你今天巡检计划下载出错次数已达到上限！";
        Notification notification = NotificationUtil.createNotification(mContext,
                channelName, pendIntent, title, message);
        notificationManager.notify(ntfTagPlanErr, notification);
    }

    final class BatteryInfoReceiver extends BroadcastReceiver {
        private PowerManager.WakeLock wakeLock = null;

        public BatteryInfoReceiver(PowerManager.WakeLock wakeLock) {
            super();
            this.wakeLock = wakeLock;
        }

        @SuppressLint("Wakelock")
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                if (null != wakeLock && !(wakeLock.isHeld())) {
                    wakeLock.acquire();
                }
            } else if (Intent.ACTION_SCREEN_ON.equals(action) || Intent.ACTION_USER_PRESENT.equals(action)) {
                if (null != wakeLock && wakeLock.isHeld()) {
                    wakeLock.release();
                }
            }else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                int level = intent.getIntExtra("level", 0); // 电池电量等级
                int scale = intent.getIntExtra("scale", 100); // 电池满时百分比
                int batteryHealth = level * 100 / scale;
                mBatteryHealth = batteryHealth;
                EventBus.getDefault().post(new DeviceInfoToolEvent(DEVICEINFO_BATTERY_CHANGED, mBatteryHealth));
            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){
                //checkDeviceInfo(DeviceInfoBean.WORK_STATE_ING);
            }
        }
    }

    public final static String DEVICEINFO_TODAY_PLAN_CHANGED = "deviceInfoTodayPlanChanged";
    public final static String DEVICEINFO_TODAY_NO_PLAN = "deviceInfoTodayNoPlan";
    public final static String DEVICEINFO_CHECK_TODAY_PLAN_FINISHED = "deviceInfoCheckTodayPlanFinished";
    public final static String DEVICEINFO_PLAN_DOWN_ERR_MAX = "deviceInfoPlanDownErrMax";
    public final static String DEVICEINFO_UNREAD_MESSAGE= "deviceInfoUnreadMessage";
    public final static String DEVICEINFO_BATTERY_CHANGED= "deviceInfoBatteryChanged";
    public final static String DEVICEINFO_CONNECTION_INFO = "deviceInfoConnectionInfo";
    public final static String DEVICEINFO_NEW_SAVED_GPS = "deviceInfoNewSavedGps";

    public static class DeviceInfoToolEvent {
        public String message;
        public Object arg;

        public DeviceInfoToolEvent(String message, Object arg) {
            this.message = message;
            this.arg = arg;
        }
    }
}
