package com.sincere.att.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sincere.att.feign.ScFeign;
import com.sincere.att.feign.XaFeign;
import com.sincere.att.logs.LogName;
import com.sincere.att.logs.LoggerUtils;
import com.sincere.att.mqtt.MqtUtils;
import com.sincere.att.vo.AttendanceInfoBean;
import com.sincere.att.vo.CheckOrderVo;
import com.sincere.att.vo.FingerOrderVo;
import com.sincere.att.vo.UserOrderVo;
import com.sincere.common.dto.smartCampus.SZ_AttendanceDto;
import com.sincere.common.dto.xiaoan.FingerDto;
import com.sincere.common.util.DateUtils;
import com.sincere.common.util.HttpClientUtils;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 所有的设备请求都会在url参数里携带SN,这是设备序列号(serial number的缩写),每个设备唯一标识
 */
@RestController
@RequestMapping("/iclock")
public class AttPushController {
    private static final Logger Log_orderFail = LoggerUtils.Logger(LogName.orderFail);
    private static final Logger Log_orderSuccess = LoggerUtils.Logger(LogName.orderSuccess);
    private static final Logger Log_kaoInfo = LoggerUtils.Logger(LogName.kaoInfo);

    private static Map<String, List<String>> cmdMap = new HashMap<>();
    private static Map<String, Integer> cmdOrderMap = new HashMap<>();

    private static String pwd = "22222222-6faf-48uh-a5a9-447ec68bfe2f";
    private static String account = "yueqingzhijiao";


    @Autowired
    ScFeign scFeign;

    @Autowired
    XaFeign xaFeign;

    @RequestMapping(value = "GetDeviceCmd", method = RequestMethod.GET)
    @ApiOperation(value = "查询待处理指令")
    @ApiImplicitParams({@ApiImplicitParam(name = "schoolId", value = "学校id"),
            @ApiImplicitParam(name = "deviceId", value = "设备id")})
    public String GetDeviceCmd(@RequestParam("schoolId") String schoolId,
                              @RequestParam("deviceId") String deviceId) {
        try {
            if(schoolId=="1221")
            {

            }
            if(StringUtils.isNotBlank(deviceId)){
                List<String> cmds = cmdMap.get(deviceId);
                if (cmds != null && cmds.size() > 0) {
                    return cmds.toString();
                }
                return "cmd is empty";
            }
            else{
                return "device not is null";
            }
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    //C:${CmdID}:Check  检查并传送新数据
    @RequestMapping(value = "GetLatestData", method = RequestMethod.GET)
    @ApiOperation(value = "检查并上传新数据")
    @ApiImplicitParams({@ApiImplicitParam(name = "schoolId", value = "学校id"),
            @ApiImplicitParam(name = "deviceId", value = "设备id")})
    public void GetLatestData(@RequestParam("schoolId") String schoolId,
                               @RequestParam("deviceId") String deviceId) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String date=simpleDateFormat.format(new Date());
        List<String> order = new ArrayList<>();
        CheckOrderVo vo = new CheckOrderVo();
        vo.setStudentName(deviceId+date);
        int number = 1;
        try {
            number = cmdOrderMap.get(deviceId);
        } catch (Exception e) {

        }
        number++;
        cmdOrderMap.put(deviceId, number);

            if (!order.contains(vo.toString())) {
                order.add(vo.toString());
            }

        cmdMap.put(deviceId, order);

    }

    @RequestMapping(value = "sendSingleUser", method = RequestMethod.GET)
    @ApiOperation(value = "下发单个用户")
    @ApiImplicitParams({@ApiImplicitParam(name = "schoolId", value = "学校id"),
            @ApiImplicitParam(name = "deviceId", value = "设备id"),
            @ApiImplicitParam(name = "studentId", value = "学生id")})
    public void sendSingleUser(@RequestParam("schoolId") String schoolId,
                               @RequestParam("deviceId") String deviceId,
                               @RequestParam("studentId") int studentId) {
//        String result1 = HttpClientUtils.httpGet2("http://campus.myjxt.com/api/EasyN/GetStudentDetail?studentid="+studentId+"&schoolId="+schoolId);
        JSONObject result = HttpClientUtils.httpGet("http://campus.myjxt.com/api/EasyN/GetStudentDetail?studentid="+studentId+"&schoolId="+schoolId);
        JSONObject array = (JSONObject) result.get("data");
        List<String> order = new ArrayList<>();
                UserOrderVo vo = new UserOrderVo();
                vo.setStudentId((Integer) array.get("studentId"));
                vo.setStudentName((String) array.get("studentName"));
                int number = 1;
                try {
                    number = cmdOrderMap.get(deviceId);
                } catch (Exception e) {

                }
                vo.setNumber(number);
                number++;
                cmdOrderMap.put(deviceId, number);
                if (vo.getStudentId() != 0) {
//                    if (vo.getStudentId() == 72196){
                    //todo:测试专用
                    if (!order.contains(vo.toString())) {
                        order.add(vo.toString());
                    }
//                    }
                }
                cmdMap.put(deviceId, order);

    }

    @RequestMapping(value = "sendSingleFinger", method = RequestMethod.GET)
    public void sendSingleFinger(@RequestParam("StudentId") int StudentId,@RequestParam(value = "deviceId") String deviceId) {

            List<String> order = new ArrayList<>();
//            for (int i = 0; i < array.size(); i++) {
//                JSONObject student = (JSONObject) array.get(i);
                FingerOrderVo vo = new FingerOrderVo();
                int number = 1;
                try {
                    number = cmdOrderMap.get(deviceId);
                } catch (Exception e) {

                }
                vo.setNumber(number);
                vo.setOrder(xaFeign.selectFinger((Integer) StudentId));
                number++;
                cmdOrderMap.put(deviceId, number);
                if (StringUtils.isNotBlank(vo.getOrder())) {
                    order.add(vo.toString());
                }
            //}
            cmdMap.put(deviceId, order);
        //}
    }

    @RequestMapping(value = "sendUser", method = RequestMethod.GET)
    public void sendUser(@RequestParam("roomId") int roomId) {
        JSONObject object = new JSONObject();
        object.put("pageIndex", 1);
        object.put("roomId", roomId);
        object.put("pageSize", 9999);
        JSONObject result = HttpClientUtils.httpPostJson("http://campus.myjxt.com/api/Room/GetListPageRoom", object.toJSONString());
        JSONArray array = (JSONArray) ((JSONObject) result.get("data")).get("roomList");
        List<String> attendanceList = scFeign.selectRoomAttendance(roomId);
        for (String attendance : attendanceList) {
            List<String> order = new ArrayList<>();
            for (int i = 0; i < array.size(); i++) {
                JSONObject student = (JSONObject) array.get(i);
                UserOrderVo vo = new UserOrderVo();
                vo.setStudentId((Integer) student.get("studentid"));
                vo.setStudentName((String) student.get("name"));
                int number = 1;
                try {
                    number = cmdOrderMap.get(attendance);
                } catch (Exception e) {

                }
                vo.setNumber(number);
                number++;
                cmdOrderMap.put(attendance, number);
                if (vo.getStudentId() != 0) {
//                    if (vo.getStudentId() == 72196){
                    //todo:测试专用
                    if (!order.contains(vo.toString())) {
                        order.add(vo.toString());
                    }
//                    }
                }
            }
                cmdMap.put(attendance, order);
        }
    }

    @RequestMapping(value = "sendFinger", method = RequestMethod.GET)
    public void sendFinger(@RequestParam("roomId") int roomId,@RequestParam(value = "deviceId",required = false) String deviceId) {
        JSONObject object = new JSONObject();
        object.put("PageIndex", 1);
        object.put("roomId", roomId);
        object.put("pageSize", 9999);
        JSONObject result = HttpClientUtils.httpPostJson("http://campus.myjxt.com/api/Room/GetListPageRoom", object.toJSONString());
        JSONArray array = (JSONArray) ((JSONObject) result.get("data")).get("roomList");
        List<String> attendanceList = scFeign.selectRoomAttendance(roomId);
        for (String attendance : attendanceList) {
            if(StringUtils.isNotBlank(deviceId)&&!attendance.contains(deviceId)) continue;
            List<String> order = new ArrayList<>();
            for (int i = 0; i < array.size(); i++) {
                JSONObject student = (JSONObject) array.get(i);
                FingerOrderVo vo = new FingerOrderVo();
                int number = 1;
                try {
                    number = cmdOrderMap.get(attendance);
                } catch (Exception e) {

                }
                vo.setNumber(number);
                vo.setOrder(xaFeign.selectFinger((Integer) student.get("studentid")));
                number++;
                cmdOrderMap.put(attendance, number);
                if (StringUtils.isNotBlank(vo.getOrder())) {
                    order.add(vo.toString());
                }
            }
            cmdMap.put(attendance, order);
        }
    }

    /**
     * 1,设备通完电以后第一个发送到后台的请求
     * 格式为 /iclock/cdata?options=all&language=xxxx&pushver=xxxx
     */
    @RequestMapping(value = "/cdata", params = {"options", "language", "pushver"}, method = RequestMethod.GET)
    public void init(String SN,String options,String language,String pushver,HttpServletRequest request,
                     @RequestParam(required = false) String PushOptionsFlag,
                     HttpServletResponse response) {
        try {
            System.out.println("设备上电:" + SN);
            if (cmdMap.get(SN) == null) {
                System.out.println("设备上线:" + SN);
                cmdMap.put(SN, new ArrayList<>());
                cmdOrderMap.put(SN, 10000);
            }
            if (scFeign.selectAttendaceWithId(SN) == null) {
                SZ_AttendanceDto attendanceDto = new SZ_AttendanceDto();
                attendanceDto.setClint_id(SN);
                attendanceDto.setClint_type("24");
                attendanceDto.setIp(request.getRemoteAddr());
                attendanceDto.setPort(request.getRemotePort());
                attendanceDto.setIntime(DateUtils.date2String(new Date(), DateUtils.format2));
                attendanceDto.setSchool_id("-1");
                attendanceDto.setState(1);
                scFeign.insertAttendance(attendanceDto);
            } else {
                scFeign.updateAttendance(SN);
            }
            String initOptions = initOptions(SN, PushOptionsFlag);
            response.getWriter().write(initOptions);//返回成功以后设备会发送心跳请求
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 2,心跳请求,会从服务器拿到命令返回   给设备
     */
    @RequestMapping("/getrequest")
    public void heartBeat(String SN, HttpServletResponse response) {
        scFeign.updateAttendance(SN);
        StringBuffer sb = new StringBuffer("OK");
        //System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"设备心跳:" + SN);
        List<String> cmds = cmdMap.get(SN);
//        if (null != cmds && cmds.size() > 10)
//            cmds = cmds.subList(0, 10);
        if (cmds == null) {//等于空说明从来没加载过,如果初始化加载过了,此时应该不为Null 只是size为0
            System.out.println("设备上线:" + SN);
            cmds = new ArrayList<>();
            cmdMap.put(SN, cmds);
            cmdOrderMap.put(SN, 10000);
        }
        if (cmds != null && cmds.size() > 0) {
            sb.setLength(0);//如果有命令就不返回OK了
            cmds.stream().forEach(cmd -> sb.append(cmd).append("\r\n\r\n"));
        }
        try {
            response.setCharacterEncoding("gbk");
            response.getWriter().write(sb.toString());
//            System.out.println("返回数据成功:" + SN + "---学生数量:" + cmds.size());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 3,候补心跳请求,正常情况下设备不发此请求,有大量数据上传的时候,不发上面的心跳,发这个请求,
     * 这个请求,服务器只能返回OK,不可以返回命令
     */
    @RequestMapping("/ping")
    public void ping(HttpServletResponse response) {
        System.out.println("考勤机心跳请求大量进来了......ping" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        try {
            response.getWriter().write("OK");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 4,设备端处理完命令以后会发送该请求,告诉服务器命令的处理结果
     */
    @RequestMapping("/devicecmd")
    public void handleCmd(String SN, @RequestBody String data, HttpServletResponse response) {
        //判断data  清空map
        //ID=10000&Return=-10&CMD=DATA 指纹下发返回return=-10,表示指纹机没有这个用户数据
        List<String> cmdList = cmdMap.get(SN);
        String[] returnList = data.split("\n");
        if (returnList != null && returnList.length > 0 && cmdList != null && cmdList.size() > 0) {
            System.out.println("----returnList:" + returnList.length);
            for (String message : returnList) {
                System.out.println("----returnList:"+ SN + "," + message);
                String number = message.substring(message.indexOf("=") + 1, message.indexOf("&"));
                String result = message.substring(message.indexOf("=", message.indexOf("&")) + 1, message.indexOf("&", message.indexOf("&") + 1));
                //if (result.equals("0")) {
                    Iterator<String> it = cmdList.iterator();
                    while (((Iterator) it).hasNext()) {
                        String b = it.next();
                        if (b.contains("C:" + number)) {
                            it.remove();

                            System.out.println("----设备接收数据"+(Integer.parseInt(result)==0?"成功":"--失败--")+":" + SN + "----number:" + number);
                        }
                    }
                    if(message.contains("CMD=DATA"))
                    {

                    }
                    if(message.contains("CMD=CHECK"))
                    {

                    }
                //}
            }

        }
        try {
            response.getWriter().write("OK");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 5 考勤数据上报
     */
    @RequestMapping(value = "/cdata")
    public void handleRtData(HttpServletRequest request, HttpServletResponse response, String SN, String table) throws UnsupportedEncodingException {
        request.setCharacterEncoding("gbk");
        String data = "";
        ByteArrayOutputStream bos = null;
        byte[] b = new byte[1024];
        try {
            InputStream is = request.getInputStream();
            bos = new ByteArrayOutputStream();
            int len = 0;
            while ((len = is.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            data = new String(bos.toByteArray(), "gbk");
        } catch (IOException e) {
            e.printStackTrace();
        }
        if ("ATTLOG".equals(table)) {
            String[] list = data.split("\t");
            String cardNo = scFeign.selectStudentNumByStudentId(Integer.valueOf(list[0]));
            if (StringUtils.isNotBlank(cardNo)) {
                String cardNo10 = new BigInteger(cardNo, 16).toString();
                //考勤日志
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String info = String.format("<AttendanceInfo submitTime=\"%s\"><Info device=\"%s\" card=\"%s\" operTime=\"%s\" direc=\"%s\"></Info></AttendanceInfo>",
                        simpleDateFormat.format(new Date()), SN, cardNo10, list[1], "-1");
                AttendanceInfoBean attendanceInfoBean = new AttendanceInfoBean();
                attendanceInfoBean.setInfo(info);
                attendanceInfoBean.setIsControl(0);
                attendanceInfoBean.setPwd(pwd);
                attendanceInfoBean.setUsername(account);

                String jsonResult = JSON.toJSONString(attendanceInfoBean);
                String urlHXY = "http://campus.myjxt.com/api/XiaoAnCommon/SendHXY";
                JSONObject jsonObject = HttpClientUtils.httpPostJson(urlHXY, jsonResult);
                //if ((int) jsonObject.get("status") == 1) {
                if ( Integer.parseInt(jsonObject.get("data").toString()) == 0) {
                    /**
                     * 签到成功发送数据到看板 add by 2020-11-17
                     */
                    sendMQMessage(SN,cardNo);

                    Log_kaoInfo.info("出入寝签到成功:" + SN + " 卡号:" + cardNo);
                } else {
                    Log_kaoInfo.info("出入寝签到失败:" + SN + " 卡号:" + cardNo + " result1:" + jsonObject.toJSONString());
                }
            } else {
                System.out.println(list[0]+":card is "+cardNo);
            }
        }
        if ("OPERLOG".equals(table)) {

            //操作日志
            if (data.substring(0, 3).contains("FP")) {
                String[] finger = data.split("FP ");
                for (int j = 0; j < finger.length; j++) {
                    String fingerInfo = finger[j];
                    if(org.springframework.util.StringUtils.isEmpty(fingerInfo)) continue;

                    //添加指纹
                    String studentId = fingerInfo .substring(fingerInfo .indexOf("=") + 1, fingerInfo .indexOf("\t", fingerInfo .indexOf("=")));
//                  String order = data.substring(3);
                    String ret= xaFeign.selectFinger(Integer.parseInt(studentId));
                    if(!org.springframework.util.StringUtils.isEmpty(ret)) continue;

                    //String order = data;
                    FingerDto fingerDto = new FingerDto();
                    fingerDto.setOrderMsg(fingerInfo);
                    fingerDto.setStudentId(Integer.valueOf(studentId));
                    fingerDto.setCreateTime(new Date());
                    xaFeign.insertFinger(fingerDto);

                }
            }
        }
        try {
            response.getWriter().write("OK");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendMQMessage(String deviceId,String cardNum) {
        //获取寝室关联的场景id
        String placeId = scFeign.selectPlaceAttendance(deviceId);

        if (null != placeId) {
            //关联的显示看板设备
            List<String> kanbanIds = scFeign.selectRoomAttendance(Integer.parseInt(placeId));

            for (int i = 0; i < kanbanIds.size(); i++) {
                String kanbanId = kanbanIds.get(i);
                String data = "{\"cmd\":\"" + 34 + "\",\"clientId\":\"" + kanbanId + "\",\"data\":{\"cardNum\":\"" + cardNum+"}}";
                MqtUtils.getInstance().sendMsg(kanbanId, data);
            }

        } else {
            String schoolId = scFeign.getSchoolIdWidthCardNum(cardNum);
            if(org.springframework.util.StringUtils.isEmpty(schoolId)||Integer.parseInt(schoolId) <=0)return;
            List<String> clintIds = scFeign.getClintIds(schoolId);
            for (int i = 0; i < clintIds.size(); i++) {
                String clintId = clintIds.get(i);
                String data = "{\"cmd\":\"" + 34 + "\",\"clientId\":\"" + clintId + "\",\"data\":{\"cardNum\":\"" + cardNum + "}}";
                MqtUtils.getInstance().sendMsg(clintId, data);
            }
        }

    }

    public static void main(String[] args) {
       /*JSONObject object = new JSONObject();
       object.put("pageIndex",1);
       object.put("roomId","13299");
       object.put("pageSize",9999);
       JSONObject result = HttpClientUtils.httpPostJson("http://campus.myjxt.com/api/Room/GetListPageRoom",object.toJSONString());
       JSONObject data = result.getJSONObject("data");
       JSONArray roomList = data.getJSONArray("roomList");
       for (int i = 0; i < roomList.size(); i++) {
           String name = roomList.getJSONObject(i).getString("name");
           String studentId = roomList.getJSONObject(i).getString("studentid");
           System.out.println(name+","+studentId);
       }*/

        String cardNo = "FF013E0F";
        String SN = "A4JS174260624";
        String cardNo10 = new BigInteger(cardNo, 16).toString();
        //考勤日志
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String info = String.format("<AttendanceInfo submitTime=\"%s\"><Info device=\"%s\" card=\"%s\" operTime=\"%s\" direc=\"%s\"></Info></AttendanceInfo>",
                simpleDateFormat.format(new Date()), SN, cardNo10, DateUtils.date2String(new Date(), DateUtils.format2), "-1");
        AttendanceInfoBean attendanceInfoBean = new AttendanceInfoBean();
        attendanceInfoBean.setInfo(info);
        attendanceInfoBean.setIsControl(0);
        attendanceInfoBean.setPwd(pwd);
        attendanceInfoBean.setUsername(account);

        String jsonResult = JSON.toJSONString(attendanceInfoBean);
        String urlHXY = "http://campus.myjxt.com/api/XiaoAnCommon/SendHXY";
        JSONObject jsonObject = HttpClientUtils.httpPostJson(urlHXY, jsonResult);
        if ((int) jsonObject.get("status") == 1) {
            Log_kaoInfo.info("出入寝签到成功:" + SN + " 卡号:" + cardNo);
        } else {
            Log_orderFail.info("出入寝签到失败:" + SN + " 卡号:" + cardNo + " result1:" + jsonObject.toJSONString());
        }
    }


    /**
     * 设备通电以后连接到服务器,需要返回的初始化参数
     *
     * @param sn
     * @param PushOptionsFlag
     * @return
     */
    private String initOptions(String sn, String PushOptionsFlag) {
        StringBuffer devOptions = new StringBuffer();
        devOptions.append("GET OPTION FROM: " + sn);
        // + "\nStamp=" + devInfo.devInfoJson.getString("Stamp")
        devOptions.append("\nATTLOGStamp=0");
        devOptions.append("\nOPERLOGStamp=0");
        devOptions.append("\nBIODATAStamp=0");
        devOptions.append("\nATTPHOTOStamp=0");
        devOptions.append("\nErrorDelay=10");//断网重连
        devOptions.append("\nDelay=5");//心跳间隔
        devOptions.append("\nTimeZone=8");//时区
        devOptions.append("\nRealtime=1");//实时上传
        devOptions.append("\nServerVer=3.0.1");//这个必须填写
//        1 考勤记录
//        2 操作日志
//        3 考勤照片
//        4 登记新指纹
//        5 登记新用户
//        6 指纹图片
//        7 修改用户信息
//        8 修改指纹
//        9 新登记人脸
//        10 用户照片
//        11 工作号码
//        12 比对照片
        devOptions.append("\nTransFlag=111111111111");//  1-12二进制位 分别代表以上含义
        System.out.println("PushOptionsFlag=============" + PushOptionsFlag);
        if (PushOptionsFlag != null && PushOptionsFlag.equals("1")) {
            // 支持参数单独获取的才要把需要获取的参数回传给设备 modifeid by max 20170926
            devOptions.append("\nPushOptions=RegDeviceType,FingerFunOn,FaceFunOn,FPVersion,FaceVersion,NetworkType,HardwareId3,HardwareId5,HardwareId56,LicenseStatus3,LicenseStatus5,LicenseStatus56");
        }
        devOptions.append("\n");
        return devOptions.toString();
    }
}