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 lombok.extern.slf4j.Slf4j;
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
@Slf4j
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";

    @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()  ;
            int  result=0;
            for(Vehiclesdetail detail : vels){
                log.info(detail.toString());
                Vehicle  v=new Vehicle();
                v.setId(UUID.randomUUID().toString());
                v.setCreate_time (new Date(Long.valueOf(vehicles.getTs())));
                v.setType(detail.getType());
                v.setDirection(detail.getDirection());
                v.setRuleTag(detail.getRuleTag());
                v.setClassification_confidence(detail.getClassification_confidence());
                v.setVideo_id(vehicles.getVideo_id());
                log.info(v.toString());
                result=traffFlowService.saveTraffFlowDetail(v);
                log.info("insertvel="+result);


            }
            //查询近五分钟的车流量，当天车流量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 void autoRule() {
        Vehicle  v=new Vehicle();
        v.setId(UUID.randomUUID().toString());
        v.setCreate_time (DateUtils.parseDate("2020-12-10 23:59:00"));
        v.setType("SEDAN1");
        v.setDirection(Long.valueOf("0"));
        v.setRuleTag("1");
        v.setClassification_confidence(Long.valueOf("0"));
        v.setVideo_id("20200603135925971_1");
        traffFlowService.saveTraffFlowDetail(v);
    }


}
