package com.casic.missiles.modular.system.service.impl;

import com.baomidou.mybatisplus.mapper.SqlRunner;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.casic.missiles.core.common.factory.CommonPermissionFactory;
import com.casic.missiles.core.common.service.ICommonPermissionService;
import com.casic.missiles.core.datascope.DataScope;
import com.casic.missiles.core.exception.GunsException;
import com.casic.missiles.core.exception.GunsExceptionEnum;
import com.casic.missiles.core.util.DateUtil;
import com.casic.missiles.core.util.ToolUtil;
import com.casic.missiles.modular.system.constant.DeviceConst;
import com.casic.missiles.modular.system.dao.DeviceMapper;
import com.casic.missiles.modular.system.dto.*;
import com.casic.missiles.modular.system.model.*;
import com.casic.missiles.modular.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.Validator;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 设备表 服务实现类
 * </p>
 *
 * @author lwh123
 * @since 2019-05-23
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {

    @Autowired
    private IDeviceTypeService deviceTypeService;

    @Autowired
    private IDeviceModelsService deviceModelsService;

    @Autowired
    private IDeviceConcentratorService deviceConcentratorService;

    @Autowired
    private IDeviceWellService deviceWellService;

    @Autowired
    private ICommonPermissionService permissionService;

    @Autowired
    private Validator validator;

    /**
     * 判断设备是否关联集中器
     *
     * @param entity 设备类型
     * @return
     */
    private Boolean isAddConcentrator(Device entity) {
        DeviceModels deviceModels = deviceModelsService.selectById(entity.getModelId());
        List<String> communis = Arrays.asList(deviceModels.getCommunication().split(","));
        return communis.contains(DeviceConst.YES);
    }

    @Override
    public boolean insert(Device entity) {
        //根据井编号查询井信息
        DeviceWellDto wellDto = this.selectWellIdByCode(entity.getWellCode());
        if (ToolUtil.isEmpty(wellDto)) {
            GunsException gunsException = new GunsException(GunsExceptionEnum.REQUEST_NULL);
            gunsException.setMessage("编号不存在");
            throw gunsException;
        }
        DeviceType deviceType = deviceTypeService.selectById(entity.getDeviceType());
        if (ToolUtil.isEmpty(deviceType)) {
            GunsException gunsException = new GunsException(GunsExceptionEnum.REQUEST_NULL);
            gunsException.setMessage("设备类型不存在");
            throw gunsException;
        }

        boolean isAddConcentrator = DeviceConst.YES.equals(deviceType.getIsNoConcent()) ? false : isAddConcentrator(entity);
        //根据集中器编号查询集中器信息
        DeviceConcentratorDto concentratorDto = null;
        if (isAddConcentrator) {
            concentratorDto = this.selectDeviceConcentorByCode(entity.getConcenCode());
            if (ToolUtil.isEmpty(concentratorDto)) {
                GunsException gunsException = new GunsException(GunsExceptionEnum.REQUEST_NULL);
                gunsException.setMessage("集中器编号不存在");
                throw gunsException;
            }
        }
        //设置默认值
        entity.setOnlineState(DeviceConst.YES);
        entity.setValid(DeviceConst.YES);
        entity.setLogtime(new Date());
        boolean flag = super.insert(entity);

        //关联设备集中器信息
        if (isAddConcentrator) {
            deviceConcentratorService.insert(createConcentrator(entity.getId(), concentratorDto.getId()));
        }
        //关联设备井盖信息
        deviceWellService.insert(createDeviceWell(entity.getId(), wellDto.getWellId()));
        return flag;
    }

    @Transactional
    @Override
    public boolean updateById(Device entity) {
        DeviceConcentrator deviceConcentrator = deviceConcentratorService.getDeviceConcentratorBydevId(entity.getId());
        DeviceWell deviceWell = deviceWellService.getDeviceWellByDevId(entity.getId());

        //根据井编号查询井信息
        if (ToolUtil.isNotEmpty(entity.getWellCode())) {
            DeviceWellDto wellDto = this.selectWellIdByCode(entity.getWellCode());
            if (ToolUtil.isEmpty(wellDto)) {
                GunsException gunsException = new GunsException(GunsExceptionEnum.REQUEST_NULL);
                gunsException.setMessage("编号不存在");
                throw gunsException;
            }
            if (!deviceWell.getWellId().equals(wellDto.getWellId())) {
                deviceWellService.deleteByDeviceId(entity.getId());
                deviceWellService.insert(createDeviceWell(entity.getId(), wellDto.getWellId()));
            }
        }

        DeviceType deviceType = deviceTypeService.selectById(entity.getDeviceType());
        if (ToolUtil.isEmpty(deviceType)) {
            GunsException gunsException = new GunsException(GunsExceptionEnum.REQUEST_NULL);
            gunsException.setMessage("设备类型不存在");
            throw gunsException;
        }
        //判断设备是否不需要关联集中器
        boolean isAddConcentrator = DeviceConst.YES.equals(deviceType.getIsNoConcent()) ? false : isAddConcentrator(entity);

        if (isAddConcentrator) {
            GunsException gunsException = new GunsException(GunsExceptionEnum.REQUEST_NULL);
            gunsException.setMessage("集中器编号不存在");
            //校验设备是否需要绑定集中器
            if (ToolUtil.isNotEmpty(entity.getConcenCode())) {
                //根据集中器编号查询集中器信息
                DeviceConcentratorDto concentratorDto = this.selectDeviceConcentorByCode(entity.getConcenCode());
                if (ToolUtil.isEmpty(concentratorDto)) {
                    throw gunsException;
                }
                //判断集中器是否修改
                if (deviceConcentrator == null || !deviceConcentrator.getConcenId().equals(concentratorDto.getId())) {
                    deviceConcentratorService.deleteByDeviceId(entity.getId());
                    deviceConcentratorService.insert(createConcentrator(entity.getId(), concentratorDto.getId()));
                }
            } else {
                throw gunsException;
            }
        } else {
            deviceConcentratorService.deleteByDeviceId(entity.getId());
        }

        return super.updateById(entity);
    }

    @Override
    public List<DeviceDto> selectDataScopePage(DataScope dataScope, Page<DeviceDto> page, String deviceType, String deptid, String beginTime, String endTime, String keywords,String isOnline, String areaId) {
        return this.baseMapper.selectDataScopePage(dataScope, page, deviceType, deptid, beginTime, endTime, keywords, isOnline, areaId);
    }

    @Override
    public DeviceWellDto selectWellIdByCode(String wellCode) {
        return this.baseMapper.selectWellIdByCode(wellCode);
    }

    @Override
    public DeviceConcentratorDto selectDeviceConcentorByCode(String concenCode) {
        return this.baseMapper.selectDeviceConcentorByCode(concenCode);
    }

    @Override
    public Device getDeviceByDevCode(String devCode) {
        Device device = new Device();
        device.setDevcode(devCode);
        device.setValid("1");
        return this.baseMapper.selectOne(device);
    }

    @Transactional
    @Override
    public List<String> addDeviceBatch(List<Device> results) {

        BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(Device.class, "设备类型导入校验");
        Map<String, Boolean> isAddConcentrator = new HashMap<>();
        List<String> list = new ArrayList<>();
        if (!ToolUtil.isEmpty(results)) {
            final Integer[] index = {0};

            results.forEach(device -> {
                index[0]++;
                validator.validate(device, beanPropertyBindingResult);
                if (beanPropertyBindingResult.hasErrors()) {
                    List<FieldError> errors = beanPropertyBindingResult.getFieldErrors();
                    errors.forEach(error -> {
                                list.add("第" + index[0] + "行 ，".concat(error.getDefaultMessage()));
                                return;
                            }
                    );
                    return;
                }

                //设备类型校验
                DeviceType deviceType = deviceTypeService.selectDeviceTypeByName(device.getDeviceTypeName());
                if (ToolUtil.isOneEmpty(deviceType) || ToolUtil.isEmpty(deviceType.getId())) {
                    list.add("第" + index[0] + "行，设备类型不存在！");
                    return;
                }


                //设备型号校验
                DeviceModels deviceModels = deviceModelsService.selectDeviceModelsBymodelName(device.getModelName());
                if (ToolUtil.isEmpty(deviceModels)) {
                    list.add("第" + index[0] + "行,设备型号不存在");
                    return;
                }
                if (!deviceModels.getDeviceType().equals(deviceType.getId())) {
                    list.add("第" + index[0] + "行,设备类型与设备型号不匹配");
                    return;
                }


                DeviceWellDto wellDto = this.selectWellIdByCode(device.getWellCode());
                if (ToolUtil.isOneEmpty(wellDto)) {
                    list.add("第" + index[0] + "行,编号不存在");
                    return;
                }

                //如果非NB则判断集中器 即设备类型包含1
                List<String> communis = Arrays.asList(deviceModels.getCommunication().split(","));
                //优先判断设备类型配置
                boolean isAdd = DeviceConst.YES.equals(deviceType.getIsNoConcent()) ? false : communis.contains(DeviceConst.YES);
                if (isAdd) {
                    DeviceConcentratorDto concentratorDto = this.selectDeviceConcentorByCode(device.getConcenCode());
                    isAddConcentrator.put(device.getDevcode(), true);
                    if (ToolUtil.isOneEmpty(concentratorDto)) {
                        list.add("第" + index[0] + "行,集中器编号不存在");
                        return;
                    }
                    device.setConcenId(concentratorDto.getId());
                } else {
                    isAddConcentrator.put(device.getDevcode(), false);
                }
                if (ToolUtil.isNotEmpty(device.getInstallDateFmt())) {
                    try {
                        device.setInstallDate(new SimpleDateFormat("yyyy-MM-dd").parse(device.getInstallDateFmt()));
                    } catch (Exception e) {
                        list.add(" 第" + index[0] + "行，时间格式不正确");
                        return;
                    }
                } else {
                    device.setInstallDate(new Date());
                }

                //设置设备相关信息
                device.setDeviceType(deviceType.getId());
                device.setModelId(deviceModels.getId());
                device.setWellId(wellDto.getWellId());

            });

            if (ToolUtil.isNotEmpty(list)) {
                return list;
            }
            //保存设备信息
            this.insertBatch(results);
            List<DeviceConcentrator> deviceConcentrators = new ArrayList<>();
            List<DeviceWell> deviceWells = new ArrayList<>();

            results.forEach(device -> {
                deviceWells.add(createDeviceWell(device.getId(), device.getWellId()));

                //判断是否关联集中器
                if (isAddConcentrator.get(device.getDevcode()))
                    deviceConcentrators.add(createConcentrator(device.getId(), device.getConcenId()));
            });

            //设备闸井关联表 设备集中器关联表
            if (ToolUtil.isNotEmpty(deviceConcentrators))
                this.deviceConcentratorService.insertBatch(deviceConcentrators);
            if (ToolUtil.isNotEmpty(deviceWells))
                this.deviceWellService.insertBatch(deviceWells);

        } else {
            list.add("导入数据不能为空");
        }

        return list;
    }

    @Override
    public List<DeviceMonitorDataDto> selectWellDataScopePage(DataScope dataScope, Page<DeviceMonitorDataDto> page, String deptid, String beginTime, String endTime, String keywords) {

        return this.baseMapper.selectWellDataScopePage(dataScope, page, deptid, beginTime, endTime, keywords);
    }

    @Override
    public List<DeviceMonitorDataDto> selectLiquidDataScopePage(DataScope dataScope, Page<DeviceMonitorDataDto> page, String deptid, String beginTime, String endTime, String keywords) {
        return this.baseMapper.selectLiquidDataScopePage(dataScope, page, deptid, beginTime, endTime, keywords);
    }

    @Override
    public List<Map<String, Object>> selectGasDataScopePage(DataScope dataScope, Page<Map<String,Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectGasDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }
    @Override
    public List<Map<String, Object>> selectTubeDataScopePage(DataScope dataScope, Page<Map<String,Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectTubeDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }

    @Override
    public List<Map<String, Object>> selectHarmfulDataScopePage(DataScope dataScope, Page<Map<String,Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectHarmfulDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }

    @Override
    public List<Map<String, Object>> selectTempDataScopePage(DataScope dataScope, Page<Map<String,Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectTempDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }


    @Override
    public List<Map<String, Object>> selectTempPressDataScopePage(DataScope dataScope, Page<Map<String, Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectTempPressDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }

    @Override
    public List<Map<String, Object>> selectDigDataScopePage(DataScope dataScope, Page<Map<String,Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectDigDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }

    @Override
    public List<Map<String, Object>> selectWellLocDataScopePage(DataScope dataScope, Page<Map<String, Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectWellLocDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }

    @Override
    public List<Map<String, Object>> selectNoiseDataScopePage(DataScope dataScope, Page<Map<String, Object>> page, String deptid, String beginTime, String endTime, String keywords) {
        List<Map<String, Object>> mapList = this.baseMapper.selectNoiseDataScopePage(dataScope,page,deptid,beginTime,endTime,keywords);
        for (Map<String, Object> map : mapList) {
            map.put("deptName",permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
        }
        return mapList;
    }

    @Override
    public List<AlarmDeptStaticsDto> alarmsStaticsByDept(Long deviceType, String beginTime, String endTime, DataScope dataScope, Long deptId) {
        List<Long> deptIds = CommonPermissionFactory.me().getSubDepts(deptId, DeviceConst.DEPT_TYPE_ORG);
        return this.baseMapper.alarmsStaticsByDept(deviceType, beginTime, endTime, dataScope, deptId, ToolUtil.isEmpty(deptIds));
    }

    @Override
    public void deleteByIds(List<Long> ids) {
        if (ToolUtil.isNotEmpty(ids)) {
            ids.forEach(id -> {
                this.baseMapper.deleteById(id);
                //删除井设备关联关系
                deviceWellService.deleteByDeviceId(id);
                //删除设备集中器关联
                deviceConcentratorService.deleteByDeviceId(id);
            });
        }
    }

    @Override
    public List<DeviceCodeSelectDto> selectDevicesByConfig(DataScope dataScope, String deviceType, String configStatus) {
        return this.baseMapper.selectDevicesByConfig(dataScope, deviceType, configStatus);
    }

    @Override
    public void registerGeTui(Long id, String clientid) {
        SqlRunner.db().delete("DELETE FROM SYS_USER_CLIENT WHERE USERID =  {0}", id);
        SqlRunner.db().insert("INSERT INTO SYS_USER_CLIENT (ID, USERID, CLIENTID,LOGTIME) VALUES ({0}, {1},{2},SYSDATE())", IdWorker.getId(), id, clientid);
    }

    public String getAreaFullNameById(String area) {
        String fullName = this.baseMapper.getArea(area);
        String pid = this.baseMapper.getAreaPId(area);
        if (pid.equals("0")) {
            return fullName;
        } else {
            fullName = getAreaFullNameById(pid) + "/" + fullName;
            return fullName;
        }
    }

    /**
     * 关联集中器
     *
     * @param deviceId
     * @param concenId
     * @return
     */
    private DeviceConcentrator createConcentrator(Long deviceId, Long concenId) {
        return new DeviceConcentrator(deviceId, concenId, 0, 1, new Date());
    }

    /**
     * 关联闸井
     *
     * @param deviceId
     * @param wellId
     * @return
     */
    private DeviceWell createDeviceWell(Long deviceId, Long wellId) {
        return new DeviceWell(deviceId, wellId, new Date(), "1");
    }


    @Override
    public List<Map<String, Object>> selectGasLiquidDataScopePage(DataScope dataScope, Page<Map<String, Object>> page, String sensorType, String deptid, String beginTime, String endTime, String keywords) {
        List<Long> deptIds = null;
        if (ToolUtil.isNotEmpty(deptid)) {
            deptIds = permissionService.getSubDepts(deptid, null);
            deptIds.add(Long.valueOf(deptid));
        }
        List<Map<String, Object>> mapList = new ArrayList<>();
        if("liquid".equals(sensorType)){
            mapList = this.baseMapper.selectGasLiquidDataLiquidScopePage(dataScope, page, deptIds, beginTime, endTime, keywords);
        }
        if("gas".equals(sensorType)){
            mapList = this.baseMapper.selectGasLiquidDataGasScopePage(dataScope, page, deptIds, beginTime, endTime, keywords);
        }
        for (Map<String, Object> map : mapList) {
            map.put("deptName", permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
            setCompany(map);
            if ("liquid".equals(sensorType)) {
                float liquiddata = Float.valueOf(String.valueOf(map.get("data")));
                if (liquiddata <= 0) {
                    map.put("data", "正常水位");
                }
            }
        }
        return mapList;
    }

    private void setCompany(Map<String, Object> dataMap) {
        if (ToolUtil.isNotEmpty(dataMap.get("deptid"))) {
            List<Long> parentDepts = permissionService.getParentDeptIds(dataMap.get("deptid").toString());
            if (ToolUtil.isNotEmpty(parentDepts)) {
                Long companyId = parentDepts.get(parentDepts.size() - 1);
                dataMap.put("companyId", companyId);
                dataMap.put("companyName", permissionService.getDeptName(companyId));
            }
        }
    }

    @Override
    public List<Map<String, Object>> selectDataList(DataScope dataScope, String wellCode, String watchType, String beginTime, String endTime) {
        if (ToolUtil.isAllEmpty(beginTime, endTime)) {
            Calendar calendar = Calendar.getInstance();
            endTime = DateUtil.getTime(calendar.getTime());
            calendar.add(Calendar.DATE, -7);
            beginTime = DateUtil.getTime(calendar.getTime());
        }
        List<Map<String, Object>> list = new ArrayList<>();
        switch (watchType) {
            case "liquid":
                list = this.baseMapper.selectLiquidDataList(dataScope, wellCode, beginTime, endTime);
                break;
            case "gas":
                list = this.baseMapper.selectGasDataList(dataScope, wellCode, beginTime, endTime);
                break;
            case "temp":
                list = this.baseMapper.selectTempDataList(dataScope, wellCode, beginTime, endTime);
                break;
            case "harmful":
                list = this.baseMapper.selectHarmfulDataList(dataScope, wellCode, beginTime, endTime);
                break;
            default:
                break;
        }
        for (Map<String, Object> map : list) {
            map.put("deptName", permissionService.getDeptName(Long.valueOf(map.get("deptid").toString())));
            setCompany(map);
        }
        return list;
    }

    @Override
    public Map<String, Object> selectWaterMeterDay(String devcode, String date) {
        Map<String, Object> map = this.baseMapper.selectWaterMeterDay(devcode, date);

        return map;
    }

    @Override
    public Map<String,Object> selectWaterMeterMonth(String devcode, String month) {
        Map<String, Object> map = this.baseMapper.selectWaterMeterMonth(devcode, month);

        return map;
    }

    @Override
    public Map<String,Object> selectWaterMeterTotal(String devcode, String year){
        Map<String, Object> map = this.baseMapper.selectWaterMeterYear(devcode, year);

        return map;
    }

    @Override
    public Map<String,Object> selectLatestWaterMeter(String devcode){
        Map<String, Object> map = this.baseMapper.selectLatestWaterMeter(devcode);

        return map;
    }
}
