package com.jpsoft.shinestar.modules.base.controller;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.jpsoft.ehome.device.EHomeDeviceManager;
import com.jpsoft.shinestar.config.OSSConfig;
import com.jpsoft.shinestar.modules.base.dto.PersonDeviceRelationDTO;
import com.jpsoft.shinestar.modules.base.entity.CompanyDeviceRelation;
import com.jpsoft.shinestar.modules.base.entity.CompanyInfo;
import com.jpsoft.shinestar.modules.base.entity.PersonDeviceRelation;
import com.jpsoft.shinestar.modules.base.service.CompanyDeviceRelationService;
import com.jpsoft.shinestar.modules.base.service.CompanyInfoService;
import com.jpsoft.shinestar.modules.base.service.PersonDeviceRelationService;
import com.jpsoft.shinestar.modules.common.utils.HttpUtil;
import com.jpsoft.shinestar.modules.common.utils.OSSUtil;
import com.jpsoft.shinestar.modules.common.utils.PojoUtils;
import com.jpsoft.shinestar.modules.common.dto.Sort;
import com.jpsoft.shinestar.modules.common.dto.MessageResult;
import com.jpsoft.shinestar.modules.base.entity.DeviceInfo;
import com.jpsoft.shinestar.modules.base.service.DeviceInfoService;
import com.jpsoft.shinestar.modules.pacs.dto.IsPersonExistVo;
import com.jpsoft.shinestar.modules.sys.entity.DataDictionary;
import com.jpsoft.shinestar.modules.uniview.channel.LapiChannel;
import com.jpsoft.shinestar.modules.pacs.service.IGuardService;
import com.jpsoft.shinestar.modules.uniview.service.ILapiService;
import com.jpsoft.shinestar.modules.uniview.utils.LapiSessionUtil;
import com.jpsoft.shinestar.modules.sys.entity.SysLog;
import com.jpsoft.shinestar.modules.sys.entity.User;
import com.jpsoft.shinestar.modules.sys.service.DataDictionaryService;
import com.jpsoft.shinestar.modules.sys.service.SysLogService;
import com.jpsoft.shinestar.modules.sys.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/base/deviceInfo")
@Api(description = "设备信息")
@Slf4j
public class DeviceInfoController {
    @Autowired
    private DeviceInfoService deviceInfoService;

    @Autowired
    private DataDictionaryService dataDictionaryService;

    @Autowired
    private IGuardService guardService;

    @Autowired
    private ILapiService lapiService;

    @Autowired
    private UserService userService;

    @Autowired
    private CompanyDeviceRelationService companyDeviceRelationService;

//    @Autowired
//    private DeviceSceneRelationService deviceSceneRelationService;

    @Autowired
    private ValueOperations<String,Object> valueOperations;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private CompanyInfoService companyInfoService;

    @Autowired
    private PersonDeviceRelationService personDeviceRelationService;

    @Autowired
    private OSSConfig ossConfig;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @ApiOperation(value="添加设备")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("add")
    public MessageResult<DeviceInfo> add(@RequestBody DeviceInfo deviceInfo,@RequestAttribute String subject){
        MessageResult<DeviceInfo> msgResult = new MessageResult<>();

        try {
            DeviceInfo item = deviceInfoService.getByDeviceNo(deviceInfo.getDeviceNo());

            if(item == null) {

                deviceInfo.setId(UUID.randomUUID().toString());
                deviceInfo.setDelFlag(false);
                deviceInfo.setCreateBy(subject);
                deviceInfo.setCreateTime(new Date());

                if ("2".equals(deviceInfo.getManufacturer())){
                    Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

                    if (loginID!=null){
                        deviceInfo.setIsOnline(true);
                    }
                }

                //是否设置远程开门时间
                if(StringUtils.isNotEmpty(deviceInfo.getRemoteOpenRangeTime())){
                    String remoteOpenRangeTime = deviceInfo.getRemoteOpenRangeTime();
                    String[] remoteOpenArray = remoteOpenRangeTime.split(",");
                    String remoteOpenStartTime = remoteOpenArray[0];
                    String remoteOpenEndTime = remoteOpenArray[1];

                    deviceInfo.setRemoteOpenStartTime(remoteOpenStartTime);
                    deviceInfo.setRemoteOpenEndTime(remoteOpenEndTime);
                }

                int affectCount = deviceInfoService.insert(deviceInfo);

                //添加信息到设备与公司关联表
                if(StringUtils.isNotEmpty(deviceInfo.getCompanyId())) {
                    //先查关联表是否存在数据
                    CompanyDeviceRelation companyDeviceRelation = companyDeviceRelationService.findByCompanyIdAndDeviceId(deviceInfo.getCompanyId(), deviceInfo.getId());
                    if (companyDeviceRelation == null) {
                        companyDeviceRelation = new CompanyDeviceRelation();
                        companyDeviceRelation.setId(UUID.randomUUID().toString());
                    }
                    companyDeviceRelation.setCompanyId(deviceInfo.getCompanyId());
                    companyDeviceRelation.setDeviceId(deviceInfo.getId());
                    //保存人脸库ID
                    companyDeviceRelation.setLibraryId("");
                    companyDeviceRelationService.insert(companyDeviceRelation);
                }

                if (affectCount > 0) {
                    msgResult.setResult(true);
                    msgResult.setData(deviceInfo);
                } else {
                    msgResult.setResult(false);
                    msgResult.setMessage("数据库添加失败");
                }
            }
            else{
                msgResult.setResult(false);
                msgResult.setMessage("设备编号已经存在，不能重复添加！");
            }
        }
        catch(Exception ex){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error(ex.getMessage(),ex);
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="创建空记录")
    @GetMapping("create")
    public MessageResult<DeviceInfo> create(){
        MessageResult<DeviceInfo> msgResult = new MessageResult<>();

        DeviceInfo deviceInfo = new DeviceInfo();

        msgResult.setData(deviceInfo);
        msgResult.setResult(true);

        return msgResult;
    }

    @ApiOperation(value="获取设备信息")
    @GetMapping("edit/{id}")
    public MessageResult<DeviceInfo> edit(@PathVariable("id") String id){
        MessageResult<DeviceInfo> msgResult = new MessageResult<>();

        try {
            DeviceInfo deviceInfo = deviceInfoService.get(id);

            if (deviceInfo != null) {
                if(StringUtils.isNotEmpty(deviceInfo.getScene())){
                    String[] sceneArray = deviceInfo.getScene().split(",");
                    List<String> sceneList = new ArrayList<>();

                    for (String scene:sceneArray) {
                        sceneList.add(scene);
                    }
                    deviceInfo.setSceneList(sceneList);
                }

                msgResult.setResult(true);
                msgResult.setData(deviceInfo);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("数据库不存在该记录!");
            }
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="更新设备信息")
    @PostMapping("update")
    public MessageResult<DeviceInfo> update(@RequestBody DeviceInfo deviceInfo,@RequestAttribute String subject){
        MessageResult<DeviceInfo> msgResult = new MessageResult<>();

        try {
            DeviceInfo item = deviceInfoService.get(deviceInfo.getId());

            if(item!=null) {
                DeviceInfo sameItem = deviceInfoService.getByDeviceNo(deviceInfo.getDeviceNo());

                if (sameItem==null || deviceInfo.getId().equals(sameItem.getId())) {
                    deviceInfo.setUpdateBy(subject);
                    deviceInfo.setUpdateTime(new Date());

                    if ("2".equals(deviceInfo.getManufacturer())){
                        Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

                        if (loginID!=null){
                            deviceInfo.setIsOnline(true);
                        }
                    }

                    //是否设置远程开门时间
                    if(StringUtils.isNotEmpty(deviceInfo.getRemoteOpenRangeTime())){
                        String remoteOpenRangeTime = deviceInfo.getRemoteOpenRangeTime();
                        String[] remoteOpenArray = remoteOpenRangeTime.split(",");

                        if (remoteOpenArray.length==2) {
                            String remoteOpenStartTime = remoteOpenArray[0];
                            String remoteOpenEndTime = remoteOpenArray[1];

                            deviceInfo.setRemoteOpenStartTime(remoteOpenStartTime);
                            deviceInfo.setRemoteOpenEndTime(remoteOpenEndTime);
                        }
                    }

                    if (StringUtils.isEmpty(deviceInfo.getScene())){
                        deviceInfo.setScene("");
                    }

                    int affectCount = deviceInfoService.update(deviceInfo);

                    if (affectCount > 0) {
                        //判断是否修改公司
                        //不相同为修改
                        if(StringUtils.isNotEmpty(deviceInfo.getCompanyId())
                                && !item.getCompanyId().equals(deviceInfo.getCompanyId())) {
                            //添加信息到设备与公司关联表
                            //先删除
                            companyDeviceRelationService.deleteByCompanyIdAndDeviceId(item.getCompanyId(), item.getId());

                            CompanyDeviceRelation companyDeviceRelation = new CompanyDeviceRelation();
                            companyDeviceRelation.setId(UUID.randomUUID().toString());
                            companyDeviceRelation.setCompanyId(deviceInfo.getCompanyId());
                            companyDeviceRelation.setDeviceId(deviceInfo.getId());
                            //保存人脸库ID
                            companyDeviceRelation.setLibraryId("");
                            companyDeviceRelationService.insert(companyDeviceRelation);
                        }
                        msgResult.setResult(true);
                        msgResult.setData(deviceInfo);
                    } else {
                        msgResult.setResult(false);
                        msgResult.setMessage("数据库更新失败");
                    }
                } else {
                    //如果修改设备编号在数据库中已有重复的设备号，则不能修改！
                    msgResult.setResult(false);
                    msgResult.setMessage("该设备编号的设备已存在，不能修改！");
                }
            }
            else{
                msgResult.setResult(false);
                msgResult.setMessage("该设备不存在！");
            }
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="删除设备")
    @PostMapping("delete/{id}")
    public MessageResult<Integer> delete(@PathVariable("id") String id,@RequestAttribute String subject){
        MessageResult<Integer> msgResult = new MessageResult<>();

        try {
            DeviceInfo deviceInfo = deviceInfoService.get(id);
//            //删除所有设备人脸库
            //清除人脸数据
            //危险操作
//            List<PacsResult> lapiResults= guardService.deleteDeviceAllCompanyLib(id);
//            for (int i = 0; i < lapiResults.size(); i++) {
//                PacsResult lapiResult = lapiResults.get(i);
//                if (lapiResult.isSuccess()) {
//                    Object obj = lapiResult.getData();
//                    //默认人脸库ID defaultFaceLibraryId
//                    //LibraryId
//                    //LibraryId -> 1585025356
//
//                    //设备上的人脸库删除成功后
//                    //执行删除设备
//                    deviceInfo.setDelFlag(true);
//                    deviceInfo.setUpdateBy(subject);
//                    deviceInfo.setUpdateTime(new Date());
//                    affectCount = deviceInfoService.update(deviceInfo);
//                }
//            }

            deviceInfo.setDelFlag(true);
            deviceInfo.setUpdateBy(subject);
            deviceInfo.setUpdateTime(new Date());
            int affectCount = deviceInfoService.update(deviceInfo);

            if (affectCount > 0) {
                companyDeviceRelationService.deleteByCompanyIdAndDeviceId(deviceInfo.getCompanyId(),deviceInfo.getId());
                msgResult.setResult(true);
                msgResult.setData(affectCount);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("删除失败");
            }
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }


    @ApiOperation(value="批量删除设备")
    @PostMapping("batchDelete")
    public MessageResult<Integer> batchDelete(@RequestBody List<String> idList,@RequestAttribute String subject){
        MessageResult<Integer> msgResult = new MessageResult<>();

        try {
            int affectCount = 0;

            for (String id : idList) {
                DeviceInfo deviceInfo = deviceInfoService.get(id);
                deviceInfo.setDelFlag(true);
                deviceInfo.setUpdateBy(subject);
                deviceInfo.setUpdateTime(new Date());

                affectCount += deviceInfoService.update(deviceInfo);

                companyDeviceRelationService.deleteByCompanyIdAndDeviceId(deviceInfo.getCompanyId(),deviceInfo.getId());
            }

            if (affectCount > 0) {
                msgResult.setResult(true);
                msgResult.setData(affectCount);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("删除失败");
            }
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="设备列表")
    @RequestMapping(value = "pageList",method = RequestMethod.POST)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "aliasName",value = "设备别名",  paramType = "query"),
            @ApiImplicitParam(name = "deviceNo",value = "编号",  paramType = "query"),
            @ApiImplicitParam(name = "address",value = "位置",  paramType = "query"),
            @ApiImplicitParam(name = "companyName",value = "企业名称",  paramType = "query"),
            @ApiImplicitParam(name = "companyId",value = "企业ID",  paramType = "query")
    })
    public MessageResult<Object> pageList(
            String aliasName,String deviceNo,String address,String companyName,String companyId,
            String code,String columnColor,String columnHeight,String type,String deviceType,String manufacturer,
            String scene,
            @RequestParam(value="pageIndex",defaultValue="1") int pageIndex,
            @RequestParam(value="pageSize",defaultValue="20") int pageSize,
            @RequestParam(value="field",defaultValue="is_online") String field,
            @RequestParam(value="direction",defaultValue="desc") String direction,
            @RequestParam(value = "exportFlag", defaultValue = "0") int exportFlag,
            @RequestAttribute String subject){
        //当前用户ID
        System.out.println(subject);

        MessageResult<Object> msgResult = new MessageResult<>();

        Map<String,Object> searchParams = new HashMap<>();

        List<Sort> sortList = new ArrayList<>();

        sortList.add(new Sort(field,direction));
        sortList.add(new Sort("a.create_time","desc"));

        User user = userService.get(subject);

        if(!userService.hasRole(user.getId(),"SYSADMIN")) {
            //非系统管理员只能查看自己单位下的设备
            CompanyInfo companyInfo = companyInfoService.get(user.getCompanyId());
            searchParams.put("companyCode", companyInfo.getCode() + "%");
//            String userCompanyId = user.getCompanyId();
//
//            List<DeviceInfo> deviceInfoList = deviceInfoService.findByCompanyId(userCompanyId);
//            List<String> deviceIdList = new ArrayList<String>();
//            if(deviceInfoList.size() > 0) {
//                for (DeviceInfo deviceInfo : deviceInfoList) {
//                    deviceIdList.add(deviceInfo.getId());
//                }
//            }else{
//                deviceIdList.add("-1");
//            }
//
//            searchParams.put("deviceIdList",deviceIdList);
        }

        if (StringUtils.isNotEmpty(aliasName)) {
            searchParams.put("aliasName","%" + aliasName + "%");
        }
        if (StringUtils.isNotEmpty(deviceNo)) {
            searchParams.put("deviceNo","%" + deviceNo + "%");
        }
        if (StringUtils.isNotEmpty(address)) {
            searchParams.put("address","%" + address + "%");
        }
        if (StringUtils.isNotEmpty(companyId)) {
            searchParams.put("companyId",companyId);
        }
        if (StringUtils.isNotEmpty(companyName)) {
            searchParams.put("companyName","%" + companyName + "%");
        }
        if (StringUtils.isNotEmpty(code)) {
            searchParams.put("code","%" + code + "%");
        }
        if (StringUtils.isNotEmpty(columnColor)) {
            searchParams.put("columnColor",columnColor);
        }
        if (StringUtils.isNotEmpty(columnHeight)) {
            searchParams.put("columnHeight",columnHeight);
        }
        if (StringUtils.isNotEmpty(type)) {
            searchParams.put("type",type);
        }
        if (StringUtils.isNotEmpty(deviceType)) {
            searchParams.put("deviceType",deviceType);
        }
        if (StringUtils.isNotEmpty(manufacturer)) {
            searchParams.put("manufacturer",manufacturer);
        }

        if (StringUtils.isNotEmpty(manufacturer)) {
            searchParams.put("manufacturer",manufacturer);
        }

        if (StringUtils.isNotEmpty(scene)) {
            searchParams.put("scene","%"+scene+"%");
        }

        Page<DeviceInfo> page = deviceInfoService.pageSearch(searchParams,pageIndex,pageSize,true,sortList);
        Map<String, DataDictionary> moduleTypeMap = dataDictionaryService.findMapByCatalogName("模块类型");
        Map<String,DataDictionary> deviceTypeMap = dataDictionaryService.findMapByCatalogName("设备类型");
        Map<String,DataDictionary> columnColorMap = dataDictionaryService.findMapByCatalogName("立柱颜色");
        Map<String,DataDictionary> columnHeightMap = dataDictionaryService.findMapByCatalogName("立柱高度");
        Map<String,DataDictionary> manufacturerMap = dataDictionaryService.findMapByCatalogName("设备厂家");
        Map<String,DataDictionary> sceneMap = dataDictionaryService.findMapByCatalogName("设备用途");

        for (DeviceInfo deviceInfo:page) {
            if(moduleTypeMap.containsKey(deviceInfo.getType())) {
                deviceInfo.setTypeN(moduleTypeMap.get(deviceInfo.getType()).getName());
            }

            if(deviceTypeMap.containsKey(deviceInfo.getDeviceType())) {
                deviceInfo.setDeviceTypeN(deviceTypeMap.get(deviceInfo.getDeviceType()).getName());
            }

            if(columnColorMap.containsKey(deviceInfo.getColumnColor())) {
                deviceInfo.setColumnColorN(columnColorMap.get(deviceInfo.getColumnColor()).getName());
            }

            if(columnHeightMap.containsKey(deviceInfo.getColumnHeight())) {
                deviceInfo.setColumnHeightN(columnHeightMap.get(deviceInfo.getColumnHeight()).getName());
            }

            if (manufacturerMap.containsKey(deviceInfo.getManufacturer())){
                deviceInfo.setManufacturerN(manufacturerMap.get(deviceInfo.getManufacturer()).getName());
            }

            if(StringUtils.isNotEmpty( deviceInfo.getScene())) {
                String[] arr = deviceInfo.getScene().split(",");
                List<String> sceneList = new ArrayList<>();
                for (String sce:arr) {
                    sceneList.add(sceneMap.get(sce).getName());
                }
                deviceInfo.setSceneList(sceneList);
            }

            if (sceneMap.containsKey(deviceInfo.getScene())){
                deviceInfo.setSceneN(sceneMap.get(deviceInfo.getScene()).getName());
            }
        }

        msgResult.setResult(true);

        if(exportFlag==1) {
            String filePath = exportXls(page);
            msgResult.setData(filePath);
        }
        else{
            Map<String, Object> dataMap = PojoUtils.pageWrapper(page);
            msgResult.setData(dataMap);
        }

        return msgResult;
    }

    private String exportXls(Page<DeviceInfo> page) {
        String downloadUrl = "";

        Workbook workbook = new HSSFWorkbook();
        Sheet sheet = workbook.createSheet();

        //表头
        Row rowTitle = sheet.createRow(0);

        String[] titles = new String[]{"序号","设备编号","内部编号","单位","设备别名","运行状态","模块类型","设备类型","立柱颜色","立柱高度","心跳信号更新时间"};

        for (int i=0;i<titles.length;i++) {
            Cell cell = rowTitle.createCell(i);
            cell.setCellValue(titles[i]);
        }

        try {
            ObjectMapper objectMapper = new ObjectMapper();

            for (int i=0;i<page.size();i++){
                DeviceInfo deviceInfo = page.get(i);
                String jsonStr = objectMapper.writeValueAsString(deviceInfo);

                JSONObject jsonObject = JSONObject.parseObject(jsonStr);
                Row row = sheet.createRow(i+1);

                int colIndex = 0;

                row.createCell(colIndex++).setCellValue(i+1);
                row.createCell(colIndex++).setCellValue(jsonObject.getString("deviceNo"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("code"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("companyName"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("aliasName"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("isOnLineN"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("typeN"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("deviceTypeN"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("columnColorN"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("columnHeightN"));
                row.createCell(colIndex++).setCellValue(jsonObject.getString("heartbeatUpdateTime"));
            }

            ByteArrayOutputStream output = new ByteArrayOutputStream();

            workbook.write(output);

            byte[] buffer = output.toByteArray();
            ByteArrayInputStream input = new ByteArrayInputStream(buffer);

            downloadUrl = OSSUtil.upload(ossConfig,"requestForLeave","设备列表.xls",input);
        }
        catch (Exception ex){
            log.error(ex.getMessage(),ex);
        }

        return downloadUrl;
    }

    @ApiOperation(value="根据IP地址和端口号查找设备")
    @PostMapping("getByIpAddressAndPort")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ipAddress",value = "IP地址", paramType = "query"),
            @ApiImplicitParam(name = "port",value = "端口号", paramType = "query")
    })
    public MessageResult<DeviceInfo> getByIpAddressAndPort( String ipAddress,String port,@RequestAttribute String subject) {
        MessageResult<DeviceInfo> msgResult = new MessageResult<>();
        try {
            DeviceInfo device = lapiService.findByIpAddressAndPort(ipAddress, port);

            msgResult.setResult(true);
            msgResult.setData(device);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }
        return msgResult;
    }


    @ApiOperation(value="获取设备信息列表")
    @PostMapping("list")
    public MessageResult<List<DeviceInfo>> list(@RequestAttribute String subject) {
        MessageResult<List<DeviceInfo>> msgResult = new MessageResult<>();
        try {
            List<DeviceInfo> list = new ArrayList<>();
            //系统管理员
            boolean isSysAdmin = userService.hasRole(subject,"SYSADMIN");

            if(!isSysAdmin){
                User user = userService.get(subject);
                String companyId = user.getCompanyId();

                List<DeviceInfo> deviceInfoList = deviceInfoService.findByCompanyId(companyId);
                List<String> deviceIdList = new ArrayList<String>();
                if(deviceInfoList.size() > 0) {
                    for (DeviceInfo deviceInfo : deviceInfoList) {
                        deviceIdList.add(deviceInfo.getId());
                    }
                }else{
                    deviceIdList.add("-1");
                }
                //list = deviceInfoService.findByDeviceIdList(deviceIdList);
                List<Sort> sortList = new ArrayList<>();
                sortList.add(new Sort("a.is_online","desc"));
                sortList.add(new Sort("a.create_time","desc"));

                Map<String, Object> searchParams = new HashMap<>();
                searchParams.put("isOnline",true);
                searchParams.put("deviceIdList",deviceIdList);

                Page<DeviceInfo> page = deviceInfoService.pageSearch(searchParams,0,500,false,sortList);
                list = page.getResult();
            }
            else{
                //list = deviceInfoService.list();

                List<Sort> sortList = new ArrayList<>();
                sortList.add(new Sort("a.is_online","desc"));
                sortList.add(new Sort("a.create_time","desc"));

                Map<String, Object> searchParams = new HashMap<>();
                searchParams.put("isOnline",true);
                Page<DeviceInfo> page = deviceInfoService.pageSearch(searchParams,0,500,false,sortList);
                list = page.getResult();
            }

            for (DeviceInfo deviceInfo:list) {
                String typeN = dataDictionaryService.findNameByCatalogNameAndValue("设备类型",deviceInfo.getType());
                deviceInfo.setTypeN(typeN);
            }

            msgResult.setResult(true);
            msgResult.setData(list);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }
        return msgResult;
    }

    @ApiOperation(value="获取设备验证规则列表")
    @PostMapping("getDeviceRule")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId",value = "设备编号", paramType = "query")
    })
    public MessageResult<Map<String,Object>> getDeviceRule(String deviceId,@RequestAttribute String subject) {
        MessageResult<Map<String,Object>> msgResult = new MessageResult<>();
        try {
            Map<String,Object> ruleMap = lapiService.getDeviceRule(deviceId);
            //ruleMap.get("RuleList");//规则状态列表
            //Mode 0安全帽,1口罩,2测温
            //Enabled 是否启用 0否,1是
            //ruleMap.get("TemperatureRule");//温度设置
            //Type -> 1 手腕1,额头0
            //Minimum -> 30
            //Maximum -> 45
            //PreAlarmOffset -> 0.300000
            //AlarmThreshold -> 37.3000000

            Map<String,Object> ruleMap2 = lapiService.getOpenDoorMode(deviceId);

            Object mode = ruleMap2.get("Mode");//温度设置
            ruleMap.put("mode",mode);
            msgResult.setResult(true);
            msgResult.setData(ruleMap);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }
        return msgResult;
    }

    @ApiOperation(value="更新设备验证规则")
    @PostMapping("saveDeviceRule")
    /**
     * @param deviceInfoId 设备id
     * @param needCap 安全帽验证 （0：不验证，1：验证）
     * @param needMask 口罩验证 （0：不验证，1：验证）
     * @param measureTemperature 测试验证 （0：不验证，1：验证）
     * @param type 测试验证类型 （0：测额温，1：测腕温）
     * @param minTemper 温度下限
     * @param maxTemper 温度上限
     * @param preAlarmOffset 温度误差
     * @param alarmThreshold 报警温度
     * @param mode 校验方式
     **/
    public MessageResult<DeviceInfo> saveDeviceRule(
            String deviceInfoId,
            Integer needCap,
            Integer needMask,
            Integer measureTemperature,
            Integer type,
            BigDecimal minTemper,
            BigDecimal maxTemper,
            Integer preAlarmEnabled,
            BigDecimal preAlarmOffset,
            BigDecimal alarmThreshold,
            String mode,
            @RequestAttribute String subject){
        MessageResult<DeviceInfo> msgResult = new MessageResult<>();
        Boolean result = false;
        try {
            lapiService.setOpenDoorMode(deviceInfoId,mode);
            result = lapiService.setDeviceRule(deviceInfoId,needCap,needMask,measureTemperature,
                    type,minTemper,maxTemper,preAlarmEnabled,preAlarmOffset,alarmThreshold);
            msgResult.setResult(result);
            msgResult.setMessage("");
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value = "查询")
    @RequestMapping(value = "query", method = RequestMethod.POST)
    public MessageResult<List> query(
            String aliasName,String companyId,
            @RequestParam(value = "limit", defaultValue = "20") int limit,
            @RequestAttribute String subject) {
        MessageResult<List> msgResult = new MessageResult<>();

        Map<String, Object> searchParams = new HashMap<>();

        List<Sort> sortList = new ArrayList<>();
        sortList.add(new Sort("a.is_online","desc"));
        sortList.add(new Sort("a.create_time","desc"));

        if (StringUtils.isNotEmpty(aliasName)) {
            searchParams.put("aliasName", "%" + aliasName + "%");
        }

        if (StringUtils.isNotEmpty(companyId)) {
            searchParams.put("bindCompanyId", companyId);
        }
        else{
            User user = userService.get(subject);
            companyId = user.getCompanyId();
            searchParams.put("bindCompanyId", companyId);
        }

        List<DeviceInfo> deviceList = deviceInfoService.pageSearch(searchParams,1, limit,false, sortList);

        msgResult.setResult(true);
        msgResult.setData(deviceList);

        return msgResult;
    }

    @ApiOperation(value="添加新设备后绑定用户")
    @GetMapping("queryBindDeviceProgress")
    public MessageResult<String> queryBindDeviceProgress(String deviceId){
        MessageResult<String> msgResult = new MessageResult<>();

        try {
            Object progress = valueOperations.get("bindNewDevice_progress_" + deviceId);

            msgResult.setResult(true);
            msgResult.setData(String.valueOf(progress));
        }
        catch (Exception ex){
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="设备用户的照片是否存在设备中")
    @PostMapping("existPersonImageInDevice")
    public MessageResult<String> existPersonImageInDevice(String deviceId){
        MessageResult<String> msgResult = new MessageResult<>();

        try {
            DeviceInfo deviceInfo = deviceInfoService.get(deviceId);
            CompanyInfo companyInfo = companyInfoService.get(deviceInfo.getCompanyId());
            deviceInfo.setCompanyName(companyInfo.getName());
            if (deviceInfo == null){
                throw new Exception("设备不存在");
            }

            if (!deviceInfo.getIsOnline()){
                throw new Exception("设备" + deviceInfo.getDeviceNo() + "不在线!");
            }

            List<PersonDeviceRelation> pdrList = personDeviceRelationService.findByDeviceId(deviceId);

            new Thread(()->{
                List<Long> idList = new ArrayList<>();
                for (PersonDeviceRelation pdf : pdrList){
                    idList.add(pdf.getPersonId());
                }
                try{
                    List<IsPersonExistVo> list =  guardService.existPersonInDevice(idList,deviceInfo);
                    personDeviceRelationService.updateListIsBound(list,deviceInfo.getId());
                }catch (Exception ex){
                    log.error(ex.getMessage(),ex);
                }

            }).start();

           /* for (PersonDeviceRelation pdr : pdrList) {
                PersonDeviceRelationDTO dto = new PersonDeviceRelationDTO();
                dto.setPersonId(pdr.getPersonId());
                dto.setDeviceId(pdr.getDeviceId());

                //PersonDeviceRelation有额外字段，所以这里转为dto
                rabbitTemplate.convertAndSend("schoolImportImageExchange", "existPersonImage", dto);
            }*/

            msgResult.setMessage("共有" + pdrList.size() + "条记录在后台更新照片状态，请登录消息队列管理界面查询查看更新进度!");
            msgResult.setResult(true);
        }
        catch (Exception ex){
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ResponseBody
    @ApiOperation(value="远程重启")
    @PostMapping("reboot")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId",value = "设备编号", required = true,paramType = "query")
    })
    public MessageResult<String> reboot(String deviceId, @RequestAttribute String subject, HttpServletRequest request){
        MessageResult<String> msgResult = new MessageResult<>();

        SysLog sysLog = new SysLog();
        sysLog.setPointcut("远程重启设备");
        sysLog.setUserId(subject);
        sysLog.setData(deviceId);
        sysLog.setCreateTime(new Date());
        sysLog.setRemoteIp(HttpUtil.getIpAddress(request));

        try {
            boolean result = guardService.reboot(deviceId);

            msgResult.setResult(result);

            if (msgResult.isResult()){
                msgResult.setMessage("远程重启成功!");
            }
            else{
                msgResult.setMessage("远程重启失败!");
            }

            sysLog.setRemark(msgResult.getMessage());
        }
        catch (Exception ex){
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        sysLogService.insert(sysLog);

        return msgResult;
    }

    @ResponseBody
    @ApiOperation(value="设备连接列表")
    @GetMapping("channelList")
    public MessageResult<List> channelList(){
        MessageResult<List> msgResult = new MessageResult<>();

        try {
            List<Map> mapList = new ArrayList<>();

            Set<String> set = LapiSessionUtil.keySet();

            for (String key : set) {
                Map<String,Object> map = new HashMap<>();
                map.put("deviceNo",key);

                //所属单位
                DeviceInfo deviceInfo = deviceInfoService.getByDeviceNo(key);

                if(deviceInfo!=null){
                    //设备别名
                    map.put("aliasName", deviceInfo.getAliasName());

                    CompanyInfo companyInfo = companyInfoService.get(deviceInfo.getCompanyId());

                    if(companyInfo!=null){
                        map.put("companyName", companyInfo.getName());
                    }
                }

                LapiChannel lapiChannel = LapiSessionUtil.get(key);

                if (lapiChannel!=null){
                    map.put("remoteAddress",lapiChannel.getChannel().remoteAddress().toString());
                    map.put("isOpen",lapiChannel.getChannel().isOpen());
                }

                mapList.add(map);
            }

            mapList.sort((Map o1, Map o2)->{
                try {
                    String companyName1 = (String) o1.get("companyName");
                    String companyName2 = (String) o2.get("companyName");

                    String deviceNo1 = (String) o1.get("deviceNo");
                    String deviceNo2 = (String) o2.get("deviceNo");

                    int result1 = companyName1.compareTo(companyName2);

                    if (result1 != 0) {
                        return result1;
                    } else {
                        return deviceNo1.compareTo(deviceNo2);
                    }
                }
                catch (Exception ex){
                    log.error(ex.getMessage(),ex);

                    return -1;
                }
            });

            //增加序号
            for (int i=0;i<mapList.size();i++){
                mapList.get(i).put("index", i+1);
            }

            msgResult.setData(mapList);
            msgResult.setResult(true);
        }
        catch (Exception ex){
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }


    @ResponseBody
    @ApiOperation(value="批量修改设备IP和端口")
    @PostMapping("updateDeviceData")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceNos",value = "设备编号", required = true,paramType = "query"),
            @ApiImplicitParam(name = "newAddress",value = "新IP", required = true,paramType = "query"),
            @ApiImplicitParam(name = "newPort",value = "新端口", required = true,paramType = "query")
    })
    public MessageResult<String> updateDeviceData(
            String deviceNos,
            String newAddress,
            String newPort,
            @RequestAttribute String subject,
            HttpServletRequest request){
        MessageResult<String> msgResult = new MessageResult<>();

        try {
            List<String> deviceNoList = null;
            if(StringUtils.isEmpty(deviceNos)){
                throw new Exception("未选择修改设备");
            }else{
                deviceNoList = Arrays.asList(deviceNos.split(","));
            }

            if(StringUtils.isEmpty(newAddress)){
                throw new Exception("新IP不能为空");
            }
            if(StringUtils.isEmpty(newPort)){
                throw new Exception("新端口不能为空");
            }

            guardService.updateDeviceServerConfig(deviceNoList,newAddress,newPort);

            msgResult.setResult(true);
            msgResult.setMessage("修改成功!");

        }
        catch (Exception ex){
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }
        return msgResult;
    }



    @ApiOperation(value="获取所有设备列表")
    @PostMapping("allDevicelist")
    public MessageResult<List<DeviceInfo>> allDevicelist(@RequestAttribute String subject) {
        MessageResult<List<DeviceInfo>> msgResult = new MessageResult<>();
        try {

            List<DeviceInfo> list = deviceInfoService.list();

            msgResult.setResult(true);
            msgResult.setData(list);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }
        return msgResult;
    }

    @ApiOperation(value="查询绑定单位列表")
    @PostMapping("queryBindCompanyList")
    public MessageResult<Map> queryBindCompanyList(
            String deviceId,String companyName,
            @RequestParam(value="pageIndex",defaultValue="1") int pageIndex,
            @RequestParam(value="pageSize",defaultValue="20") int pageSize,
            @RequestParam(value="field",defaultValue="is_online") String field,
            @RequestParam(value="direction",defaultValue="desc") String direction,
            @RequestAttribute String subject){
        //当前用户ID
        System.out.println(subject);

        MessageResult<Map> msgResult = new MessageResult<>();

        Map<String,Object> searchParams = new HashMap<>();

        try {
            List<Sort> sortList = new ArrayList<>();

            sortList.add(new Sort(field, direction));
            sortList.add(new Sort("a.create_time", "asc"));

            if (StringUtils.isNotEmpty(companyName)) {
                searchParams.put("companyName", "%" + companyName + "%");
            }

            searchParams.put("deviceId", deviceId);

            Page<CompanyDeviceRelation> page = companyDeviceRelationService.pageSearch(searchParams, pageIndex, pageSize, true, sortList);

            msgResult.setData(PojoUtils.pageWrapper(page));
            msgResult.setResult(true);
        }
        catch (Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setMessage(ex.getMessage());
            msgResult.setResult(false);
        }

        return msgResult;
    }

    @PostMapping("unbindCompany")
    @ApiOperation(value="解除与单位关联")
    public MessageResult<Integer> unbindCompany(String deviceId,String companyId){
        MessageResult<Integer> messageResult = new MessageResult<>();

        try {
            int affectCount = companyDeviceRelationService.deleteByCompanyIdAndDeviceId(companyId,deviceId);

            //todo 填写具体代码
            messageResult.setData(affectCount);
            messageResult.setResult(true);
        }
        catch (Exception ex){
            log.error(ex.getMessage(),ex);

            messageResult.setResult(false);
            messageResult.setMessage(ex.getMessage());
        }

        return messageResult;
    }

    @ApiOperation(value="将设备与用户绑定")
    @PostMapping("bindDeviceToPerson")
    public MessageResult<Integer> bindDeviceToPerson(String deviceId){
        MessageResult<Integer> msgResult = new MessageResult<>();
        Integer affectCount;

        String key = "bindNewDevice_" + deviceId;

        try {
            DeviceInfo deviceInfo = deviceInfoService.get(deviceId);

            if (!deviceInfo.getIsOnline()){
                throw new Exception("该设备不在线!");
            }

            boolean locked = valueOperations.setIfAbsent(key,1,1, TimeUnit.MINUTES);

            if(!locked){
                throw new Exception("正在批量绑定中...");
            }

            affectCount = personDeviceRelationService.bindNewDevice(deviceId);
//            PersonDeviceRelationDTO dto = new PersonDeviceRelationDTO();
//            dto.setPersonId(vo.getPersonId());
//            dto.setDeviceId(deviceInfo.getId());
//
//            rabbitTemplate.convertAndSend("importImageExchange", "importImage", dto);


            if (locked){
                boolean deleted = redisTemplate.delete(key);
                System.out.println(deleted);
            }

            msgResult.setData(affectCount);
            msgResult.setResult(true);
        }
        catch (Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }



    @PostMapping("canteenDeviceList")
    @ApiOperation(value="用途为食堂的设备列表")
    public MessageResult<Object> canteenDeviceList(){
        MessageResult<Object> messageResult = new MessageResult<>();

        try {
            List<DeviceInfo> list = deviceInfoService.findByScene("%4%");

            //todo 填写具体代码
            messageResult.setData(list);
            messageResult.setResult(true);
        }
        catch (Exception ex){
            log.error(ex.getMessage(),ex);

            messageResult.setResult(false);
            messageResult.setMessage(ex.getMessage());
        }

        return messageResult;
    }

    @ApiOperation(value="获取设备人脸检测规则")
    @PostMapping("getFaceDetectionRule")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId",value = "设备编号", paramType = "query")
    })
    public MessageResult<JSONObject> getFaceDetectionRule(String deviceId,@RequestAttribute String subject) {
        MessageResult<JSONObject> msgResult = new MessageResult<>();

        try {
            JSONObject responseBody = lapiService.getFaceDetectionRule(deviceId);

            msgResult.setResult(true);
            msgResult.setData(responseBody);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }
        return msgResult;
    }

    @ApiOperation(value="更新设备验证规则")
    @PostMapping("setFaceDetectionRule")
    public MessageResult<JSONObject> setFaceDetectionRule(@RequestBody JSONObject requestBody,
            @RequestAttribute String subject){
        MessageResult<JSONObject> msgResult = new MessageResult<>();

        try {
            String deviceId = requestBody.getString("deviceId");
            JSONObject data = requestBody.getJSONObject("data");

            JSONObject responseBody = lapiService.setFaceDetectionRule(deviceId,data);

            msgResult.setResult(true);
            msgResult.setData(responseBody);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="获取人脸库权限")
    @PostMapping("getPeopleLibPermission")
    public MessageResult<JSONObject> getPeopleLibPermission(String deviceId,
                                                          String libId,
                                                          @RequestAttribute String subject) {
        MessageResult<JSONObject> msgResult = new MessageResult<>();

        try {
            JSONObject responseBody = lapiService.getPeopleLibPermission(deviceId,libId);

            msgResult.setResult(true);
            msgResult.setData(responseBody);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }
        return msgResult;
    }

    @ApiOperation(value="设置人脸库权限")
    @PostMapping("setPeopleLibPermission")
    public MessageResult<JSONObject> setPeopleLibPermission(@RequestBody JSONObject requestBody,
                                                          @RequestAttribute String subject){
        MessageResult<JSONObject> msgResult = new MessageResult<>();

        try {
            String deviceId = requestBody.getString("deviceId");
            String libId = requestBody.getString("libId");
            JSONObject data = requestBody.getJSONObject("data");

            JSONObject responseBody = lapiService.setPeopleLibPermission(deviceId,libId,data);

            msgResult.setResult(true);
            msgResult.setData(responseBody);
        }
        catch(Exception ex){
            log.error(ex.getMessage(),ex);
            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }
}
