package com.zcxk.controller;

import com.zcxk.dto.*;
import com.zcxk.entity.*;
import com.zcxk.model.AjaxMessage;
import com.zcxk.model.LoginUser;
import com.zcxk.model.ResultStatus;
import com.zcxk.service.*;
import com.zcxk.util.ByteArrayUtils;
import com.zcxk.util.RedisUtil;
import com.zcxk.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;

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

import org.springframework.web.bind.annotation.*;

/**
 * 标签信息页面控制器
 * @author WYY
 * @date 2020-12-02 09:29
 */
@RestController
@RequestMapping("/monitorinfo")
@Api(tags = "标签信息")
public class MonitorInfoController {

    @Autowired
    private MonitorInfoService monitorInfoService;
    @Autowired
    private DeviceParmService deviceParmService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SceneService sceneService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private AlarmDetailsService alarmDetailsService;
    @Autowired
    private DeviceAttributeSpecsService deviceAttributeSpecsService;
    @Autowired
    private DeviceAttributeService deviceAttributeService;
    @Autowired
    private MonitorDataReportService monitorDataReportService;
    @Autowired
    private DeviceSetupMethodService deviceSetupMethodService;
    @Autowired
    private DeviceSetupRecordService deviceSetupRecordService;


    @ApiOperation(value = "按场景ID查询供水量出水量耗药量耗电量(已废弃)")
    @RequestMapping(value = "/findTotalUsageBySceneId", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage<SceneUsageDto> findTotalUsageBySceneId(@ApiParam(value = "场景ID", required = true) @RequestParam Long id, @ApiParam(value = "类型(0综合调度 1综合展示)", required = false) @RequestParam(required = false) Integer... type) {
        SceneUsageDto sceneUsageDto = new SceneUsageDto();
        //查询场景下的所有设备信息
        sceneUsageDto.setYieldWaterUsage(monitorDataReportService.getAmountCount(null, id.intValue(), null, 3, 1).doubleValue());
        sceneUsageDto.setIntakeWaterUsage(monitorDataReportService.getAmountCount(null, id.intValue(), null, 4, 1).doubleValue());
        sceneUsageDto.setPowerUsage(monitorDataReportService.getAmountCount(null, id.intValue(), null, 5, 1).doubleValue());
        sceneUsageDto.setDrugUsage(monitorDataReportService.getAmountCount(null, id.intValue(), null, 6, 1).doubleValue());
        if (type != null && type.length > 0) {
            sceneUsageDto.setYieldWaterUsage(sceneUsageDto.getYieldWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getYieldWaterUsage()).divide(BigDecimal.valueOf(10000), 3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setIntakeWaterUsage(sceneUsageDto.getIntakeWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getIntakeWaterUsage()).divide(BigDecimal.valueOf(10000), 3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setPowerUsage(sceneUsageDto.getPowerUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getPowerUsage()).divide(BigDecimal.valueOf(10000), 3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setDrugUsage(sceneUsageDto.getDrugUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getDrugUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
        } else {
            sceneUsageDto.setYieldWaterUsage(sceneUsageDto.getYieldWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getYieldWaterUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setIntakeWaterUsage(sceneUsageDto.getIntakeWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getIntakeWaterUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setPowerUsage(sceneUsageDto.getPowerUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getPowerUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setDrugUsage(sceneUsageDto.getDrugUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getDrugUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
        }
        return new AjaxMessage<>(ResultStatus.OK, sceneUsageDto);
    }

    @ApiOperation(value = "按场景ID查询供水量出水量耗药量耗电量")
    @RequestMapping(value = "/findTotalUsageBySceneIdForComDsiplay", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage<SceneUsageDto> findTotalUsageBySceneIdForComDsiplay(@ApiParam(value = "场景ID", required = true) @RequestParam Long id, @ApiParam(value = "场景类型(0水源 1水厂 2泵站)", required = false) @RequestParam(required = false) Integer type) {
        SceneUsageDto sceneUsageDto = new SceneUsageDto();

        //查询场景下的所有设备信息
        BigDecimal amount1 = monitorDataReportService.getAmountCount(null, id.intValue(), null, 3, 1);
        sceneUsageDto.setYieldWaterUsage(amount1 != null ? amount1.doubleValue() : 0);

        BigDecimal amount2 = monitorDataReportService.getAmountCount(null, id.intValue(), null, 4, 1);
        sceneUsageDto.setIntakeWaterUsage(amount2 != null ? amount2.doubleValue() : 0);
        BigDecimal amount3 = monitorDataReportService.getAmountCount(null, id.intValue(), null, 5, 1);
        sceneUsageDto.setPowerUsage(amount3 != null ? amount3.doubleValue() : 0);
        BigDecimal amount4 = monitorDataReportService.getAmountCount(null, id.intValue(), null, 6, 1);
        sceneUsageDto.setDrugUsage(amount4 != null ? amount4.doubleValue() : 0);
        sceneUsageDto.setCollectDate(monitorDataReportService.getLastCollectTime(null, id.intValue(), null, 3, 1));
        if (type.equals(1) || type.equals(0)) {
            sceneUsageDto.setYieldWaterUsage(sceneUsageDto.getYieldWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getYieldWaterUsage()).divide(BigDecimal.valueOf(10000), 3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setIntakeWaterUsage(sceneUsageDto.getIntakeWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getIntakeWaterUsage()).divide(BigDecimal.valueOf(10000), 3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setPowerUsage(sceneUsageDto.getPowerUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getPowerUsage()).divide(BigDecimal.valueOf(10000), 3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setDrugUsage(sceneUsageDto.getDrugUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getDrugUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
        } else {
            sceneUsageDto.setYieldWaterUsage(sceneUsageDto.getYieldWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getYieldWaterUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setIntakeWaterUsage(sceneUsageDto.getIntakeWaterUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getIntakeWaterUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setPowerUsage(sceneUsageDto.getPowerUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getPowerUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
            sceneUsageDto.setDrugUsage(sceneUsageDto.getDrugUsage() != null ? BigDecimal.valueOf(sceneUsageDto.getDrugUsage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() : 0d);
        }
        return new AjaxMessage<>(ResultStatus.OK, sceneUsageDto);
    }

    @ApiOperation(value = "按场景ID查询所有标签信息")
    @RequestMapping(value = "/findBySceneId", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage<List<MonitorInfoEntity>> findBySceneId(
            @ApiParam(value = "场景ID", required = true) @RequestParam Long id,
            @ApiParam(value = "图片类型(0鸟瞰图 1工艺图)", required = false) @RequestParam(required = false) Integer imageType,
            @ApiParam(value = "设备ID", required = false) @RequestParam(required = false) Long deviceId,
            @ApiParam(value = "类型(0综合调度 1综合展示)", required = false) @RequestParam(required = false) Integer... type
    ) {
        MonitorInfoEntity monitorInfoEntity = new MonitorInfoEntity();
        monitorInfoEntity.setSceneId(id);
        if (imageType != null) {
            monitorInfoEntity.setImageType(imageType);
        }
        if (type != null && type.length > 0) {
            monitorInfoEntity.setType(type[0]);
        }
        if (deviceId != null) {
            monitorInfoEntity.setDeviceId(deviceId);
        }
        List<MonitorInfoEntity> page = monitorInfoService.findList(monitorInfoEntity);
        for (MonitorInfoEntity item : page) {
            switch (item.getMonitorType().intValue()) {
                case 0:
                    getMonitorInfo(id, item);
                    break;
                case 3:
                    updateCommonState(id, 3, item);
                    break;
                case 4:
                    updateCommonState(id, 4, item);
                    break;
                case 5:
                    updateCommonState(id, 5, item);
                    break;
            }
        }
        return new AjaxMessage<>(ResultStatus.OK, page);
    }

    /**
     * 更新指令状态
     *
     * @param sceneId
     * @param item
     */
    public void updateCommonState(Long sceneId, Integer type, MonitorInfoEntity item) {
        DeviceSetupRecordEntity parm = new DeviceSetupRecordEntity();
        parm.setDeviceId(item.getDeviceId());
        parm.setAttributeId(item.getAttributeId());
        parm.setType(type);
        if (type == 4 || type == 3) {
            //更新压力值或状态值 泵状态0关 1开 TODO 后续需要统一
            item.setAttributeValue(monitorDataReportService.getDeviceAttributeValue(item.getDeviceCode(), item.getAttributeId()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
        }
        //查询报警信息
        List<AlarmDetailsDto> alarmDetailsDtos = alarmDetailsService.selectByDeviceAttributeId(sceneId, item.getDeviceId().intValue(), item.getAttributeId().intValue());
        if (alarmDetailsDtos.size() > 0) {
            item.setIsAlarm(1);
        } else {
            item.setIsAlarm(0);
        }
        DeviceSetupRecordEntity recordEntity = deviceSetupRecordService.selectLastOne(parm);
        if (recordEntity != null) {
            item.setCommonState(recordEntity.getState());
        }
    }

    /**
     * 更新标签值
     *
     * @param sceneId
     * @param item
     */
    public void getMonitorInfo(Long sceneId, MonitorInfoEntity item) {
        //查询报警信息
        List<AlarmDetailsDto> alarmDetailsDtos = alarmDetailsService.selectByDeviceId(sceneId, item.getDeviceId().intValue());
        Map<Integer, AlarmDetailsDto> mapAlarm = new HashMap<>();
        //将缓存中的实时数据放到map中方便进行遍历
        for (AlarmDetailsDto alarmDetailsDto : alarmDetailsDtos) {
            mapAlarm.put(alarmDetailsDto.getAttributeId(), alarmDetailsDto);
        }
        byte[] bytes = redisUtil.get(("sms_water_" + item.getDeviceCode()).getBytes());
        if (bytes != null && bytes.length > 0) {
            MonitorDataEntity monitorDataEntity = (MonitorDataEntity) ByteArrayUtils.bytesToObject(bytes).get();
            Map<Long, MonitorDataValueEntity> map = new HashMap<>();
            //将缓存中的实时数据放到map中方便进行遍历
            for (MonitorDataValueEntity dateValue : monitorDataEntity.getDataValues()) {
                map.put(dateValue.getAttributeId(), dateValue);
            }
            //判断如果是标签则进行map中取值
            if (item.getMonitorType().equals(0L))//标签
            {
                //按属性ID查询标签值
                DeviceAttributeSpecsEntity deviceAttributeSpecsEntity = new DeviceAttributeSpecsEntity();
                deviceAttributeSpecsEntity.setAttributeId(item.getAttributeId());
                List<DeviceAttributeSpecsEntity> deviceAttributeSpecsEntities = deviceAttributeSpecsService.findList(deviceAttributeSpecsEntity);
                if (map.containsKey(item.getAttributeId())) {
                    Double value = map.get(item.getAttributeId()).getDataValue();
                    if (value != null) {
                        if (deviceAttributeSpecsEntities.size() > 0) {
                            for (DeviceAttributeSpecsEntity specsEntity : deviceAttributeSpecsEntities) {
                                if (Integer.valueOf(specsEntity.getSpecsValue()) == value.intValue()) {
                                    item.setMonitorValue(specsEntity.getSpecsName());
                                }
                            }

                        } else {
                            DeviceAttributeEntity deviceAttributeEntity = deviceAttributeService.getById(item.getAttributeId());
                            String unit = "";
                            if (deviceAttributeEntity != null && deviceAttributeEntity.getUnit() != null) {
                                unit = deviceAttributeEntity.getUnit();
                            }
                            item.setMonitorValue(String.format("%.3f", map.get(item.getAttributeId()).getDataValue()) + unit);
                        }
                    }
                }
                //判断是否报警
                if (mapAlarm.containsKey(item.getAttributeId().intValue())) {
                    item.setIsAlarm(1);
                    item.setMonitorValue(item.getMonitorValue() + "(" + mapAlarm.get(item.getAttributeId().intValue()).getAlarmRange() + ")");
                } else {
                    item.setIsAlarm(0);
                }
            }
        }
    }

    @RequestMapping(value = "getDeviceParmByDeviceId", method = RequestMethod.GET)
    @ApiOperation(value = "查询单个设备参数信息(标签设置)")
    public AjaxMessage<List<DeviceParmEntity>> getByDeviceId(@ApiParam(value = "场景id", required = true) @RequestParam Integer sceneId, @ApiParam(value = "设备id", required = true) @RequestParam Integer id) {
        return new AjaxMessage<>(ResultStatus.OK, deviceParmService.selectByDeviceIdForGis(sceneId, id));
    }

    /**
     * 新增
     */
    @ApiOperation(value = "单个新增")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<Integer> addMonitorInfo(@ApiParam(value = "标签信息", required = true) @RequestBody MonitorInfoEntity monitorInfo) {
        if (monitorInfo == null) {
            return new AjaxMessage<>(ResultStatus.DEVICE_PARENT_ALREADY_EXISTS);
        }
        LoginUser currentUser = UserUtil.getCurrentUser();
        monitorInfo.setTenantId(currentUser.getTenantId());
        monitorInfo.setStatus(1);
        monitorInfo.setDateCreate(new Date());
        monitorInfo.setDateUpdate(new Date());
        monitorInfo.setCreateBy(currentUser.getName());
        monitorInfo.setUpdateBy(currentUser.getName());
        //校验参数
        int result = monitorInfoService.addMonitorInfo(monitorInfo) ? 1 : 0;
        return new AjaxMessage<>(ResultStatus.OK, result);
    }

    /**
     * 批量新增
     */
    @RequestMapping(value = "/batchAdd", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "批量新增或修改(按设备)")
    public AjaxMessage<Integer> addMonitorInfo(@ApiParam(value = "标签信息", required = true) @RequestBody ArrayList<MonitorInfoEntity> monitorInfos) {
        LoginUser currentUser = UserUtil.getCurrentUser();
        if (monitorInfos.size() == 0) {
            return new AjaxMessage<>(ResultStatus.DEVICE_PARENT_ALREADY_EXISTS);
        }
        for (MonitorInfoEntity item : monitorInfos) {
            item.setTenantId(currentUser.getTenantId());
            item.setStatus(1);
            item.setDateCreate(new Date());
            item.setDateUpdate(new Date());
            item.setCreateBy(currentUser.getName());
            item.setUpdateBy(currentUser.getName());
        }
        int result = monitorInfoService.saveOrUpdateBatch(monitorInfos) ? 1 : 0;
        return new AjaxMessage<>(ResultStatus.OK, result);
    }

    /**
     * 修改
     */
    @ApiOperation(value = "按ID查询标签")
    @RequestMapping(value = "/selectById", method = RequestMethod.GET)
    public AjaxMessage<MonitorInfoEntity> selectById(@ApiParam(value = "ID", required = true) @RequestParam Long id) {
        MonitorInfoEntity monitorInfo = monitorInfoService.findMonitorInfoById(id);
        return new AjaxMessage<>(ResultStatus.OK, monitorInfo);
    }

    /**
     * 修改保存标签信息
     */
    @ApiOperation(value = "单个编辑")
    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<Integer> editMonitorInfo(@ApiParam(value = "标签信息", required = true) @RequestBody MonitorInfoEntity monitorInfo) {
        int result = monitorInfoService.updateMonitorInfoById(monitorInfo) ? 1 : 0;
        return new AjaxMessage<>(ResultStatus.OK, result);
    }

    /**
     * 删除
     */
    @ApiOperation(value = "批量删除")
    @RequestMapping(value = "/deleteByIds", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<Integer> del(@ApiParam(value = "场景类型ID", required = true) @RequestBody Long[] ids) {
        int result = monitorInfoService.delMonitorInfoByIds(ids) ? 1 : 0;
        return new AjaxMessage<>(ResultStatus.OK, result);
    }

    /**
     * 操作标签--查询设备属性
     */
    @ApiOperation(value = "操作标签--查询设备属性")
    @RequestMapping(value = "/getSceneParmBySceneId", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage<List<DeviceParmEntity>> getSceneParmBySceneId(@ApiParam(value = "场景类型ID", required = true) Long id) {
        List<DeviceParmEntity> deviceParmEntities = deviceParmService.selectByScendId(id.intValue());
        return new AjaxMessage<>(ResultStatus.OK, deviceParmEntities);
    }

    /**
     * 操作标签--进行指令操作
     */
    @ApiOperation(value = "操作标签--进行指令操作")
    @RequestMapping(value = "/setSetupForDevice", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage<Integer> setSetupForDevice(
            @ApiParam(value = "标签ID", required = true) @RequestParam Long id,
            @ApiParam(value = "参数", required = true) @RequestParam String parms,
            @ApiParam(value = "密钥", required = true) @RequestParam String password) {
        //校验密钥
        boolean isPass = deviceSetupMethodService.checkPassword(password);
        if (!isPass) {
            return new AjaxMessage<>(ResultStatus.OP_PASSWORD_ERROR);
        }
        //查询操作方法
        try {
            MonitorInfoEntity monitorInfo = monitorInfoService.findMonitorInfoById(id);
            if (monitorInfo != null) {
                Integer type = monitorInfo.getMonitorType().intValue();
                long deviceId = monitorInfo.getDeviceId();
                long attributeId = monitorInfo.getAttributeId();
                long sceneId = monitorInfo.getSceneId();
                int result = deviceSetupMethodService.setSetupForDevice(type, sceneId, deviceId, attributeId, parms) ? 1 : 0;
                return new AjaxMessage<>(ResultStatus.OK, result);
            }
        } catch (Exception ex) {
            return new AjaxMessage<>(ResultStatus.ERROR_500, 0);
        }
        return new AjaxMessage<>(ResultStatus.OK, 0);
    }
}
