package com.gci.boot.modules.monitor.service.impl;

import cn.hutool.Hutool;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.gci.boot.common.util.FormatUtil;
import com.gci.boot.common.util.JsonUtil;
import com.gci.boot.common.util.RedisUtil;
import com.gci.boot.constant.CacheConstant;
import com.gci.boot.modules.basedata.entity.TbVehicle;
import com.gci.boot.modules.basedata.service.ITbVehicleService;
import com.gci.boot.modules.gis.vo.GisRedisVehicleVo;
import com.gci.boot.modules.monitor.enums.VehicleStatusEnum;
import com.gci.boot.modules.monitor.service.IMonitorService;
import com.gci.boot.modules.monitor.vo.RunningbusVO;
import com.gci.boot.modules.video.service.IVideoService;
import com.gci.boot.modules.video.vo.VideoDeviceVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gci.boot.modules.gis.entity.TbGisRunningbus;
import com.gci.boot.modules.gis.mapper.TbGisRunningbusMapper;
import com.gci.boot.modules.gis.service.ITbGisRunningbusService;
import com.gci.boot.modules.monitor.enums.DirectionEnum;
import com.gci.boot.modules.monitor.vo.AlarmCountVO;
import com.gci.boot.modules.monitor.vo.OverallMonitorVO;
import com.gci.boot.modules.monitor.vo.VehicleTreeVO;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MonitorServiceImpl implements IMonitorService {

    @Autowired
    private ITbGisRunningbusService runningbusService;
    @Autowired
    private TbGisRunningbusMapper runningbusMapper;
    @Autowired
    private IVideoService videoService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ITbVehicleService vehicleService;

    /**
     * 获取全局监控车辆数据
     * @param statusType
     * @return
     */
    @Override
    public List<OverallMonitorVO> getOverallVehicle(String statusType, String plateNumber, String projectId, String vehicleType){
        //status -1在线，2-离线，3-故障告警，4-围栏告警，5-超速告警，6-主动安全告警
        List<OverallMonitorVO> list = runningbusMapper.queryOverallVehicle(statusType,plateNumber,projectId,vehicleType);
        return list;
    }

    /**
     * 获取所有车辆对应项目，为空的归到其它
     * @param plateNumber
     * @return
     */
    @Override
    public List<VehicleTreeVO> getVehicleTree(String plateNumber){
        List<VehicleTreeVO> treeVO = runningbusMapper.queryProjrctVehicle(plateNumber);
        return treeVO;
    }

    /**
     * 获取各状态车辆数量
     * @return
     */
    @Override
    public List<AlarmCountVO> getVehicleCount(){
        LambdaQueryWrapper<TbGisRunningbus>  busQuery = new LambdaQueryWrapper<>();
        List<TbGisRunningbus> busList = runningbusMapper.selectList(busQuery);
        List<AlarmCountVO> list = new ArrayList<>();
        AlarmCountVO vo = new AlarmCountVO(VehicleStatusEnum.ALL.getType(),VehicleStatusEnum.ALL.getStatusType(),busList.stream().count());
        AlarmCountVO vo1 = new AlarmCountVO(VehicleStatusEnum.IS_ONLINE.getType(), VehicleStatusEnum.IS_ONLINE.getStatusType(),
                busList.stream().filter(item->Objects.nonNull(item.getIsOnline()) && 1 == item.getIsOnline()).count());
        AlarmCountVO vo2 = new AlarmCountVO(VehicleStatusEnum.NO_ONLINE.getType(), VehicleStatusEnum.NO_ONLINE.getStatusType(),
                busList.stream().filter(item->Objects.nonNull(item.getIsOnline()) && 0 == item.getIsOnline()).count());
        AlarmCountVO vo3 = new AlarmCountVO(VehicleStatusEnum.FAULT.getType(), VehicleStatusEnum.FAULT.getStatusType(),
                busList.stream().filter(item->Objects.nonNull(item.getFaultAlarm()) && 1 == item.getFaultAlarm()).count());
        AlarmCountVO vo4 = new AlarmCountVO(VehicleStatusEnum.FENCE.getType(), VehicleStatusEnum.FENCE.getStatusType(),
                busList.stream().filter(item->Objects.nonNull(item.getFenceAlarm()) && 1 == item.getFenceAlarm()).count());
        AlarmCountVO vo5 = new AlarmCountVO(VehicleStatusEnum.SPEED.getType(), VehicleStatusEnum.SPEED.getStatusType(),
                busList.stream().filter(item->Objects.nonNull(item.getSpeedingAlarm()) && 1 == item.getSpeedingAlarm()).count());
        AlarmCountVO vo6 = new AlarmCountVO(VehicleStatusEnum.SAFETY.getType(), VehicleStatusEnum.SAFETY.getStatusType(),
                busList.stream().filter(item->Objects.nonNull(item.getSafetyAlarm()) && 1 == item.getSafetyAlarm()).count());
        AlarmCountVO vo7 = new AlarmCountVO(VehicleStatusEnum.WORK.getType(), VehicleStatusEnum.WORK.getStatusType(),
                busList.stream().filter(item->Objects.nonNull(item.getIsWork()) && 1 == item.getIsWork()).count());
        list.add(vo);
        list.add(vo1);
        list.add(vo2);
        list.add(vo3);
        list.add(vo4);
        list.add(vo5);
        list.add(vo6);
        list.add(vo7);
        return list;
    }

    /**
     * 获取车辆详情
     * @param plateNumber
     * @return
     */
    @Override
    public OverallMonitorVO getVehicleInfo(String plateNumber){
        OverallMonitorVO vo = runningbusMapper.queryVehicleInfo(plateNumber);
        if(StrUtil.isNotBlank(vo.getDir())){
            vo.setDirection(DirectionEnum.get(vo.getDir()));
        }
        return vo;
    }

    @Override
    public VideoDeviceVO getVehicleVideoChannel(String plateNumber) {
        VideoDeviceVO vo = videoService.getVideoDevice(plateNumber);
        return vo;
    }

    @Override
    public RunningbusVO getRunningbusInfo(String plateNumber) {
        LambdaQueryWrapper<TbGisRunningbus> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TbGisRunningbus::getPlateNumber,plateNumber).last(" limit 1 ");
        TbGisRunningbus tbGisRunningbus = runningbusMapper.selectOne(queryWrapper);
        if(Objects.nonNull(tbGisRunningbus)){
            RunningbusVO vo = new RunningbusVO();
            //
            LambdaQueryWrapper<TbVehicle> vehicleLambdaQueryWrapper = new LambdaQueryWrapper<>();
            vehicleLambdaQueryWrapper.eq(TbVehicle::getPlateNumber,plateNumber).last(" limit 1 ");
            TbVehicle tbVehicle = vehicleService.getOne(vehicleLambdaQueryWrapper);
            if(Objects.nonNull(tbVehicle)){
                vo.setVehicleBrand(tbVehicle.getVehicleBrand());
                vo.setVehicleModel(tbVehicle.getVehicleModel());
                vo.setVehicleType(tbVehicle.getVehicleType());
            }

            BeanUtil.copyProperties(tbGisRunningbus,vo);
            if(StrUtil.isNotBlank(tbGisRunningbus.getVehicleJson())){
                vo.setVehicleJSONObject(JSONUtil.parseObj(tbGisRunningbus.getVehicleJson()));
            }
            if(StrUtil.isNotBlank(tbGisRunningbus.getAlarmDataJson())){
                vo.setAlarmDataJSONObject(JSONUtil.parseObj(tbGisRunningbus.getAlarmDataJson()));
            }
            if(StrUtil.isNotBlank(tbGisRunningbus.getElectricMotorJson())){
                String handleElectricMotorJson = FormatUtil.replaceStatusValues("status",tbGisRunningbus.getElectricMotorJson());
                vo.setElectricMotorJSONArray(JSONUtil.parseArray(handleElectricMotorJson));
                //转速取最大值
                double controllerTemperature = 0.0;
                double temperature = 0.0;
                for (int i = 0; i < vo.getElectricMotorJSONArray().size(); i++) {
                    if((Integer)vo.getElectricMotorJSONArray().getJSONObject(i).get("rpm") > vo.getMaxRpm()){
                        vo.setMaxRpm((Integer)vo.getElectricMotorJSONArray().getJSONObject(i).get("rpm"));
                    }
                    if(i==0){
                        controllerTemperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("controllerTemperature").toString());
                        temperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("temperature").toString());
                        vo.setMaxControllerTemperature(String.valueOf(controllerTemperature));
                        vo.setMaxTemperature(String.valueOf(temperature));
                    }
                    if(Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("controllerTemperature").toString()) > controllerTemperature){
                        controllerTemperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("controllerTemperature").toString());
                        vo.setMaxControllerTemperature(String.valueOf(controllerTemperature));
                    }
                    if(Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("temperature").toString()) > temperature){
                        temperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("temperature").toString());
                        vo.setMaxTemperature(String.valueOf(temperature));
                    }
                }
            }
            return vo;
        }
        return null;
    }

    @Override
    public List<GisRedisVehicleVo> getVehicleFenceInfo(String plateNumber) {
        String key = CacheConstant.VEHICLE_FENCE_KEY + plateNumber;
        Object obj = RedisUtil.get(key);
        if(Objects.nonNull(obj)){
            List<GisRedisVehicleVo> gisRedisVehicleVos = JSONUtil.toList(JSONUtil.toJsonPrettyStr(obj),GisRedisVehicleVo.class);
            gisRedisVehicleVos = gisRedisVehicleVos.stream().filter(b->{ return b.isWithinFenceTime(new Date()); }).collect(Collectors.toList());
            return gisRedisVehicleVos;
        }

        return null;
    }



}
