package com.unis.detectionnum.server.schedule.job;

import com.unis.detectionnum.common.vo.*;
import com.unis.detectionnum.server.domain.DeviceOperateDomain;
import com.unis.detectionnum.server.domain.ScanPointsDomain;
import com.unis.detectionnum.server.entity.DeviceOperateDO;
import com.unis.detectionnum.server.service.DeviceAlarmService;
import com.unis.detectionnum.server.service.DeviceParamService;
import com.unis.detectionnum.server.service.ScanPointsService;
import com.unis.detectionnum.server.utils.CommonDataMeasure;
import com.unis.detectionnum.server.utils.SocketUtils;
import com.unis.detectionnum.server.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;

@Component
@Slf4j
public class DetectionNumNewJob implements Job {

    private static ScheduledExecutorService scheduler = null;

    @Autowired
    private ScanPointsService pointsService;

    @Autowired
    private DeviceParamService deviceParamService;

    @Autowired
    private DeviceAlarmService deviceAlarmService;

    @Autowired
    private ServerSocket serverSocket;

    @Autowired
    DeviceOperateDomain deviceOperateDomain;

    @Autowired
    ScanPointsDomain scanPointsDomain;

    SocketUtils socketUtils = new SocketUtils();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        //SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        String sbcode = context.getJobDetail().getJobDataMap().get("sbCode").toString();
        log.info("定时任务开始执行，***************************设备code为：" + sbcode);
        //新设备（天津设备）
        monitorStart(sbcode);
    }


    /*
        问题：1.判断上一次异常断开或者不满足条件再去扫描一次（加可信度条件）
             2.产生告警（完善智能电话、短信信息入库）
             3.旧设备产生告警问题
    */
    //定义初始化设备编码
    String sbcode = "";

    //监听端口号
    public void monitorStart(String sbCode) {
        System.out.printf("new-------------------------------11111111111111");
        //给全局设备编码赋值
        sbcode = sbCode;
        log.info(new Date().toString() + "***设备id***" + sbcode);
        Socket socket = null;
        try {
            DeviceInfoQueryVO deviceInfoQueryVO = new DeviceInfoQueryVO();
            deviceInfoQueryVO.setSbCode(sbCode);
            DeviceInfoVO deviceInfoVO = deviceParamService.getDeviceProbe(deviceInfoQueryVO);
            String sbIpdz = deviceInfoVO.getSbIpdz();
            //计数防止死循环
            int temp = 0;
            while (true) {
                //超过10秒没有连接返回数据自动断开连接
                serverSocket.setSoTimeout(10000);
                socket = serverSocket.accept();

                log.info("***开始监听***socket地址：" + socket);
                log.info(new Date().toString() + "***设备的ip及其端口号***" + socket.getRemoteSocketAddress());
                log.info(new Date().toString() + "***连接成功***");
                ClientHandler handler = new ClientHandler(socket);
                Thread t = new Thread(handler);
                t.start();
                break;
                //设定输入流读取阻塞超时时间(10秒收不到客户端消息判定断线)
               /* String sId = socketUtils.sendRequest(socket, "");
                if (sId.contains(sbIpdz)) {
                    log.info("***开始监听***socket地址：" + socket);
                    log.info(new Date().toString() + "***设备的ip及其端口号***" + socket.getRemoteSocketAddress());
                    log.info(new Date().toString() + "***连接成功***");
                    ClientHandler handler = new ClientHandler(socket);
                    Thread t = new Thread(handler);
                    t.start();
                    break;
                }
                try {
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                temp++;
                if (temp == 10) {
                    log.info("设备ID配置有误,与数据库没有匹配的设备");
                    break;
                }*/
            }
        } catch (Exception e) {

            e.printStackTrace();
            log.info("连接超时socket为： " + socket);
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException eio) {
                eio.printStackTrace();
            }
            //连接失败，保存告警信息
            DeviceAlarmVO deviceAlarmVO = new DeviceAlarmVO();
            deviceAlarmVO.setCreateDate(new Date());
            deviceAlarmVO.setType(2);
            deviceAlarmVO.setSbCode(sbCode);
            deviceAlarmVO.setRemark("探头连接失败");
            deviceAlarmVO.setId(UUIDUtils.getUUID());
            deviceAlarmService.saveDeviceAlarm(deviceAlarmVO);
        }
    }

    private class ClientHandler implements Runnable {
        private Socket socket;

        public ClientHandler(Socket socket) {
            System.out.println("into");
            this.socket = socket;
        }

        @Override
        public void run() {
            //开始扫描
            scanBegin(socket, sbcode);
        }
    }

    //设备连接异常计数
    int temp2 = 0;
    /**
     * 开始扫描
     *
     * @param socket socket
     * @param sbCode 设备编码
     */
    public void scanBegin(Socket socket, String sbCode) {
        //初始化开始扫描时间
        Date scanStart = new Date();
        //查询上次扫描对应的扫描记录id（operateId）
        String operateId = pointsService.getOperateId(sbCode);
        try {
            //超过10秒没有连接返回数据自动断开连接
            socket.setSoTimeout(10000);
//            socket.connect(socket.getRemoteSocketAddress(),7000);
            log.info(scanStart.toString() + "***开启扫描***初始化扫描code为：" + operateId);
            //第二次扫描结果
            List<GetXYVO> NoZList2 = pointsService.getNoZList(operateId);
            //第一次扫描结果
            List<GetXYVO> NoZList = pointsService.getNoZList2(operateId);
            //如果NoZList.size()为0  上一次扫描完毕
            if (NoZList.size() == 0 && NoZList2.size() == 0) {
                //开启扫描
                // scanStart：开始扫描的时间；sbcode：设备id；operateId：操作id
                pointsService.Completescan(socket, scanStart, sbCode);
            } else {
                // 上次扫描未完成 从中间开始扫描
                //获取扫描高度
                DeviceOperateDO deviceOperateDO = deviceOperateDomain.selectByPrimaryKey(operateId);
                Double smgd = deviceOperateDO.getSmgd();
                Double smax = deviceOperateDO.getSmax();
                Double smby = deviceOperateDO.getSmby();

                /*
                 *  h：扫描高度；仓房的实际高度；scanStart：开始扫描的时间；sbcode：设备id；
                 *  上次扫描未完成 从中间开始扫描
                 */
                DeviceOperateVO currentOperate = pointsService.getOperate(sbCode, smgd, scanStart, 2, smax, smby);
                double cfHeight = currentOperate.getCfgd();
                double zLXGD = currentOperate.getZLXGD();
                double wd = currentOperate.getWd();
                currentOperate.setId(operateId);
                if (NoZList.size() > 0) {
                    log.info("***中间开始扫描扫描第一次start***  ");
                    Double cfsmgdz = pointsService.midland(socket, scanStart, sbCode, operateId, smgd, cfHeight, zLXGD, wd, NoZList);
                    log.info("***中间开始扫描扫描第一次end返回最高点z***  ");
                    //第一次扫描完删除临时数据xyz
//                    scanPointsDomain.deleteByoperateId(operateId);
                    log.info("***中间开始扫描扫描第1次的第2次start***  ");
                    pointsService.secondScanByMaxZ(sbCode, currentOperate, scanStart, socket, cfHeight, zLXGD, wd, cfsmgdz);
                    log.info("***中间开始扫描扫描第1次的第2次end***  ");
                    socketUtils.sendRequest(socket, CommonDataMeasure.VERTICAL_DOWN);
                }
                if (NoZList2.size() > 0) {
                    log.info("***中间开始扫描扫描第二次start***  ");
                    pointsService.midland2(socket, scanStart, sbCode, deviceOperateDO, smgd, cfHeight, zLXGD, wd, NoZList2);
                    log.info("***中间开始扫描扫描第二次end***  ");
                    socketUtils.sendRequest(socket, CommonDataMeasure.VERTICAL_DOWN);
                }
            }
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            log.info(scanStart.toString() + "***扫描超时重新扫描***socket为：" + socket + " 设备编码：" + sbCode);
            scanBegin(socket, sbCode);
        }catch (SocketException e) {
            temp2++;
            e.printStackTrace();
            log.info(scanStart.toString() + "***设备连接异常：" + socket + "  设备编码：" + sbCode);
            if (temp2 < 3){
                monitorStart(sbCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info(scanStart.toString() + "***扫描异常***socket为：" + socket + "  设备编码：" + sbCode);
        } finally {
            log.info(new Date().toString() + "***扫描完成***");
            if (socket != null) {
                try {
                    log.info(new Date().toString() + "***socket关闭***" + socket.getRemoteSocketAddress());
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
