package com.hzjt.controller;

import com.google.common.util.concurrent.RateLimiter;
import com.hzjt.domain.*;
import com.hzjt.handler.WebSocket;
import com.hzjt.mapper.SbtdspsrMapper;
import com.hzjt.service.ImportService;
import com.hzjt.service.TraffFlowService;
import com.hzjt.util.DateUtils;
import com.hzjt.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


@RestController
public class TraffController {
    @Autowired
    ImportService importService;

    @Autowired
    WebSocket webSocket;

    private Map<String, RateLimiter> rateLimiterMap;
    private String port;
    private String dept;
    private Integer rate = 10;
    private SbtdspsrMapper sbtdspsrMapper;

    @Autowired
    TraffFlowService traffFlowService;




//    @Autowired
//    private SimpMessagingTemplate template;


    private static final String TYPE = "TRAFFIC_INCIDENT_ALARM";
    private static final Logger log = LoggerFactory.getLogger(TraffController.class);

    @Autowired
    public TraffController(
            @Value("${port}") String port,
            @Value("${message.dept}") String dept,
            @Value("${message.rate}") Integer rate, SbtdspsrMapper sbtdspsrMapper) {

        this.port = port;
        this.rate = rate;
        this.dept = dept.substring(0, 5);
        this.sbtdspsrMapper = sbtdspsrMapper;
        rateLimiterMap = new ConcurrentHashMap<>(16);
    }

    @PostMapping("/alarmevent")
    public ResultObj rece(@RequestBody Alarm trffClientMessage) {


        log.debug("/event/receive接收到数据:" + trffClientMessage.toString());
        if (!TYPE.equals(trffClientMessage.getType())) {
            log.info("type类型不正确" + trffClientMessage.toString());
            return ResultObj.error(ResponseEnum.E_1002.getCode(), "type类型不正确");
        }

        log.debug("/event/receive data:" + trffClientMessage.toString());

        if (trffClientMessage.getImg_urls().isEmpty()) {
            log.info("img_urls值不能为空" + trffClientMessage.toString());
            return ResultObj.error(ResponseEnum.E_1004.getCode(), "img_urls值不能为空");
        }
        if (StringUtils.isBlank(trffClientMessage.getIncident_type())) {
            log.info("incident_type值不能为空" + trffClientMessage.toString());
            return ResultObj.error(ResponseEnum.E_1004.getCode(), "incident_type值不能为空");
        }
        String videoId = trffClientMessage.getVideo_id();

        if (StringUtils.isBlank(videoId) || !videoId.contains("_") || videoId.split("_").length != 2) {
            log.info("video_id值异常 值为:" + videoId);
            return ResultObj.error(ResponseEnum.E_1002.getCode(), "video_id值异常 值为:" + videoId);
        }
        /* 限流 */
        if (!getRateLimiter(videoId).tryAcquire()) {
            log.info("[事件推送]->设备" + videoId + "-推送已达到限流限制");
            return ResultObj.error(ResponseEnum.E_9999.getCode(), "设备" + videoId + "请求过于频繁");
        }

        String[] sbAndTd = videoId.split("_");
        String sbbh = sbAndTd[0];
        int tdbh = Integer.valueOf(sbAndTd[1]) + 1;

        List<Sbtdspsr> sbtdspsrs = sbtdspsrMapper.selectBySbbh(sbbh, tdbh);
        if (sbtdspsrs.isEmpty()) {
            log.info("设备为:" + sbbh + ",通道为:" + tdbh + "未录入(备案)");
            return ResultObj.error(ResponseEnum.E_1002.getCode(), "设备为:" + sbbh + ",通道为:" + tdbh + "未录入(备案)");
        }
        String xzbh = sbtdspsrs.get(0).getXzbh();
        if (xzbh.length() != 12) {
            log.info("设备为:" + sbbh + ",通道为:" + tdbh + "配置的行政区划" + xzbh + "不合规");
            return ResultObj.error(ResponseEnum.E_1002.getCode(), "设备为:" + sbbh + ",通道为:" + tdbh + "配置的行政区划不合规");
        }
        //ts  時間轉成正常時間
            trffClientMessage.setDept(xzbh);
            Map map = new HashMap();
            map.put("type", "alarm");
            map.put("data", trffClientMessage);
            WebSocket.GroupSending(JsonUtil.beanToString(map));

        try { // 清空redis中的部分旧数据
            importService.cleanCache();
            // 将参数result中的部分数据存入redis中，并把格式校验成功的数据发布至对应频道中
            importService.cacheAndPublish(JsonUtil.beanToString(trffClientMessage));

        } catch (Exception e) {
            log.error("MessageController receive putData error：" + e.toString());
            //return ResultObj.error(ResponseEnum.E_9999.getCode(), e.toString());
        }
        return ResultObj.ok(trffClientMessage);
    }


    private RateLimiter getRateLimiter(String videoId) {
        RateLimiter rateLimiter;
        if (rateLimiterMap.containsKey(videoId)) {
            rateLimiter = rateLimiterMap.get(videoId);
        } else {
            RateLimiter value = RateLimiter.create(rate);
            rateLimiter = rateLimiterMap.putIfAbsent(videoId, value);
            if (rateLimiter == null) {
                rateLimiter = value;
            }
        }
        return rateLimiter;
    }



    //车流量推送
    @PostMapping("/traffflow")
    public ResultObj traffflow(@RequestBody Vehicles vehicles) {

        if ("TRAFFIC_STATISTICS_VEHICLES".equalsIgnoreCase(vehicles.getType())) {
            String time=DateUtils.formatDate(new Date(Long.valueOf(vehicles.getTs())));
            vehicles.setTs(time);
            String[] sbAndTd = vehicles.getVideo_id().split("_");
            String sbbh = sbAndTd[0];
            int tdbh = Integer.valueOf(sbAndTd[1]) + 1;
            //重置videoid
            vehicles.setVideo_id(sbbh+"_"+tdbh);
            log.debug("/event/receive接收到数据:" + vehicles.toString());
            //直接放入表中
            traffFlowService.saveTraffFlow(vehicles);
           List<Vehiclesdetail> vels=vehicles.getObjs()  ;
           for(Vehiclesdetail detail : vels){
               log.info(detail.toString());
               detail.setObj_id(UUID.randomUUID().toString());
               detail.setVehiclesid(vehicles.getId());
               traffFlowService.saveTraffFlowDetail(detail);
           }
            //查询近五分钟的车流量，当天车流量websocket  直接推送过去

            log.info("schedule >>>>>>>>>> WebSocket");
            //根据连接的name ，群发根据videoid  查询的结果
            webSocket.GroupSendingByVideoid(vehicles.getVideo_id());
        }
        return ResultObj.ok();
    }


    //获取自动规则
    @PostMapping("/autoRule")
    public ResultObj autoRule(@RequestBody AutoRule rules) {
//        log.info(rules.toString());
        Map map = new HashMap();
        map.put("type", "rule");
        map.put("data", rules);
        webSocket.AppointSending(rules.getVideo_id(),JsonUtil.beanToString(map));
        return ResultObj.ok();
    }

    //获取自动规则
    @GetMapping("/test")
    public ResultObj autoRule() {
        AutoRule rule=new  AutoRule();
        Map<String, BigDecimal> v=new HashMap<>();
        v.put("x",BigDecimal.valueOf(111.2));
        v.put("y",BigDecimal.valueOf(64.09232));
        Map<String, BigDecimal>  v1=new HashMap();
        v1.put("x",BigDecimal.valueOf(111.2));
        v1.put("y",BigDecimal.valueOf(64.09232));

        Map<String, BigDecimal>  v2=new HashMap();
        v2.put("x",(BigDecimal.valueOf(111.2)));
        v2.put("y",BigDecimal.valueOf(64.000923232));
        List<Map<String, BigDecimal> > list=new ArrayList<>();
        list.add(v);
        list.add(v1);
        list.add(v2);

        List<Map<String, BigDecimal>> list2=new ArrayList<>();
        list2.add(v);
        list2.add(v1);
        list2.add(v2);

        List  list3=new ArrayList();
        list3.add(list);
        list3.add(list3);
        rule.setRule_area(list3);
        //webSocket.AppointSending(rules.getVideo_id(),JsonUtil.beanToString(map));
        return ResultObj.ok();
    }


}
