package com.huimv.admin.device.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huimv.admin.device.dao.entity.FarmDeviceEntity;
import com.huimv.admin.device.dao.entity.SysCameraAreaEntity;
import com.huimv.admin.device.dao.repo.FarmDeviceRepo;
import com.huimv.admin.device.dao.repo.SysCameraAreaEntityRepo;
import com.huimv.admin.device.service.IDevice;
import com.huimv.admin.device.utils.*;
import com.huimv.common.utils.Result;
import com.huimv.common.utils.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @Project : huimv.shiwan
 * @Package : com.huimv.biosafety.uface.controller
 * @Description : TODO
 * @Version : 1.0
 * @Author : ZhuoNing
 * @Create : 2020-12-25
 **/
@Service
@Slf4j
public class DeviceImpl implements IDevice {
    @Autowired
    private FarmDeviceRepo deviceRepo;
    @Autowired
    private DateUtil dateUtil;
    @Autowired
    private MathUtil mathUtil;
    @Autowired
    private HttpTemplete httpTemplete;
    @Autowired
    private TextUtil textUtil;
    @Value("${farm.device.sync}")
    private boolean dataSync;
    @Value("${farm.device.addService}")
    private String deviceAddService;
    @Value("${farm.device.editService}")
    private String deviceEditService;
    @Value("${farm.device.removeService}")
    private String deviceRemoveService;
    @Value("farm.env-service.port")
    private String envServicePort;
    @Value("farm.env-service.name")
    private String envServiceName;
    @Autowired
    private SysCameraAreaEntityRepo sysCameraAreaEntityRepo;

    /**
     * @Method : newDevice
     * @Description : 添加设备
     * @Params : [deviceName, deviceCode, deviceType, factory, worker, mainParams, state, record, farmId]
     * @Return : com.huimv.common.utils.Result
     * @Author : ZhuoNing
     * @Date : 2021/12/8
     * @Time : 22:03
     */
    @Override
    public Result newDevice(String deviceName, String deviceCode, String deviceType, String factory, String worker, String mainParams, Integer state, String record, Integer farmId) throws UnsupportedEncodingException {
        //
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
        FarmDeviceEntity deviceEntity = new FarmDeviceEntity();
        deviceEntity.setDeviceCode(deviceCode);
        deviceEntity.setDeviceName(deviceName);
        deviceEntity.setDeviceType(deviceType);
        deviceEntity.setFactory(factory);
        deviceEntity.setFarmId(farmId);
        deviceEntity.setMainParams(mainParams);
        deviceEntity.setRecord(record);
        deviceEntity.setWorker(worker);
        deviceEntity.setState(state);
        deviceEntity.setLastTime(new Timestamp(new Date().getTime()));
        deviceEntity.setDataId(idWorker.newId());
        deviceEntity.setDownTime(new Timestamp(new Date().getTime()));
        deviceEntity.setLockinState(2);
        FarmDeviceEntity outFarmDeviceEntity = deviceRepo.saveAndFlush(deviceEntity);
        log.info("数据中心添加设备信息>>"+outFarmDeviceEntity);
        //同步牧场端设备数据
        if(dataSync){
            log.info("同步牧场端设备数据。");
            //从数据库查询出牧场id
            String farmIp = _getFarmIP(farmId);
            String serviceUrl = farmIp + deviceAddService;
            log.info("serviceUrl>>"+serviceUrl);
            String data = textUtil.encode(JSON.toJSONString(outFarmDeviceEntity));
            log.info("base64密文>>"+data);
            //提交请求
            httpTemplete.doPostSimple(serviceUrl,data);
        }
        return new Result(ResultCode.SUCCESS, outFarmDeviceEntity);
    }

    //获取牧场
    private String _getFarmIP(Integer farmId){
        // 读取牧场公网IP
        SysCameraAreaEntity sysCameraAreaEntity = sysCameraAreaEntityRepo.getCameraIP(farmId);
        if(sysCameraAreaEntity == null){
            return null;
        }else{
            String publicUrl = sysCameraAreaEntity.getPublicUrl();
            String[] urlArray =  publicUrl.split(":");
            String farmIP = urlArray[0];
            //farmEnvService = farmIP+":"+envServicePort+"/"+envServiceName;
        }
        return  "http://192.168.1.49:8091";
    }

    /**
     * @Method : editDevice
     * @Description : 编辑设备
     * @Params : [deviceName, deviceCode, deviceType, factory, worker, mainParams, state, record, farmId, id]
     * @Return : com.huimv.common.utils.Result
     * @Author : ZhuoNing
     * @Date : 2021/12/8
     * @Time : 22:03
     */
    @Override
    public Result editDevice(String deviceName, String deviceCode, String deviceType, String factory, String worker, String mainParams, Integer state, String record, Integer farmId, Integer id) throws UnsupportedEncodingException {
        //
        Optional<FarmDeviceEntity> optional = deviceRepo.findById(id);
        if (!optional.isPresent()) {
            return new Result(10001, "该记录已不存在.", false);
        }
        FarmDeviceEntity deviceEntity = optional.get();
//        deviceEntity.setId(id);
        deviceEntity.setDeviceCode(deviceCode);
        deviceEntity.setDeviceName(deviceName);
        deviceEntity.setDeviceType(deviceType);
        deviceEntity.setFactory(factory);
        deviceEntity.setFarmId(farmId);
        deviceEntity.setMainParams(mainParams);
        deviceEntity.setRecord(record);
        deviceEntity.setWorker(worker);
        deviceEntity.setState(state);
        deviceEntity.setLastTime(new Timestamp(new Date().getTime()));
        deviceEntity.setDownTime(new Timestamp(new Date().getTime()));
        deviceEntity.setLockinState(2);
        FarmDeviceEntity outFarmDeviceEntity = deviceRepo.saveAndFlush(deviceEntity);
        log.info("数据中心添加设备信息>>"+outFarmDeviceEntity);
        //同步牧场端设备数据
        if(dataSync){
            log.info("同步牧场端设备数据。");
            //从数据库查询出牧场id
            String farmIp = _getFarmIP(farmId);
            String serviceUrl = farmIp + deviceEditService;
            log.info("serviceUrl>>"+serviceUrl);
            String data = textUtil.encode(JSON.toJSONString(outFarmDeviceEntity));
            log.info("base64密文>>"+data);
            //提交请求
            httpTemplete.doPostSimple(serviceUrl,data);
        }
        return new Result(ResultCode.SUCCESS, outFarmDeviceEntity);
    }

    /**
     * @Method : removeDevice
     * @Description : 删除设备
     * @Params : [ids]
     * @Return : com.huimv.common.utils.Result
     * @Author : ZhuoNing
     * @Date : 2021/12/8
     * @Time : 22:02
     */
    @Override
    public Result removeDevice(Integer id, Integer farmId) throws UnsupportedEncodingException {
//        String[] idArray = ids.split(",");
//        List idList = new ArrayList<>();
//        for (int a = 0; a < idArray.length; a++) {
//            idList.add(Integer.parseInt(idArray[a]));
//        }
//        deviceRepo.deleteAllByIdInBatch(idList);
        Optional<FarmDeviceEntity> optional = deviceRepo.findById(id);
        if (!optional.isPresent()) {
            String ERROR_INFO = "该记录已不存在.";
            log.error(ERROR_INFO);
            return new Result(10001, ERROR_INFO, false);
        }
        //
        deviceRepo.deleteById(id);
        FarmDeviceEntity deviceEntity = optional.get();

        //同步牧场端设备数据
        if(dataSync){
            log.info("同步牧场端设备数据。");
            //从数据库查询出牧场id
            String farmIp = _getFarmIP(farmId);
            String serviceUrl = farmIp + deviceRemoveService;
            log.info("serviceUrl>>"+serviceUrl);
            String data = textUtil.encode(String.valueOf(deviceEntity.getDataId()));
            log.info("base64密文>>"+data);
            //提交请求
            httpTemplete.doPostSimple(serviceUrl,data);
        }
        return new Result(ResultCode.SUCCESS);
    }

    /**
     * @Method      : removeBatichDevice
     * @Description : 
     * @Params      : [ids, farmId]
     * @Return      : com.huimv.common.utils.Result
     * 
     * @Author      : ZhuoNing
     * @Date        : 2021/12/16       
     * @Time        : 10:07
     */
    @Override
    public Result removeBatichDevice(String ids, Integer farmId) {
        String[] idArray = ids.split(",");
        List idList = new ArrayList<>();
        for (int a = 0; a < idArray.length; a++) {
            idList.add(Integer.parseInt(idArray[a]));
        }
        deviceRepo.deleteAllByIdInBatch(idList);
        return new Result(ResultCode.SUCCESS);
    }

    /**
     * @Method : listDevice
     * @Description : 列表查询设备
     * @Params : [deviceName, deviceCode, deviceType, factory, worker, state, farmId, startDate, endDate, pageNo, pageSize]
     * @Return : com.huimv.common.utils.Result
     * @Author : ZhuoNing
     * @Date : 2021/12/8
     * @Time : 22:02
     */
    @Override
    public Result listDevice(String deviceName, String deviceCode, String deviceType, String factory, String worker, Integer state, Integer farmId, String startDateText, String endDateText, Integer pageNo, Integer pageSize) {
        Specification<FarmDeviceEntity> sf = (Specification<FarmDeviceEntity>) (root, criteriaQuery, criteriaBuilder) -> {
            //
            List<Predicate> predList = new ArrayList<>();
            if (null != farmId) {
                predList.add(criteriaBuilder.equal(root.get("farmId").as(Integer.class), farmId));
            }
            if (null != deviceName) {
                predList.add(criteriaBuilder.equal(root.get("deviceName").as(String.class), deviceName));
            }
            if (null != deviceCode) {
                predList.add(criteriaBuilder.equal(root.get("deviceCode").as(String.class), deviceCode));
            }
            if (null != factory) {
                predList.add(criteriaBuilder.equal(root.get("factory").as(String.class), factory));
            }
            if (null != worker) {
                predList.add(criteriaBuilder.equal(root.get("worker").as(String.class), worker));
            }
            if (null != startDateText) {
                Date startDate = dateUtil.parseDate(startDateText);
                predList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("lastTime").as(Date.class), startDate));
            }
            if (null != endDateText) {
                Date endDate = dateUtil.parseDatePlus(endDateText);
                predList.add(criteriaBuilder.lessThanOrEqualTo(root.get("lastTime").as(Date.class), endDate));
            }
            if (null != state) {
                predList.add(criteriaBuilder.equal(root.get("state").as(Integer.class), state));
            }
            //
            Predicate[] pred = new Predicate[predList.size()];
            Predicate and = criteriaBuilder.and(predList.toArray(pred));
            criteriaQuery.where(and);
            //
            List<Order> orders = new ArrayList<>();
            orders.add(criteriaBuilder.desc(root.get("id")));
            return criteriaQuery.orderBy(orders).getRestriction();
        };
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize);
        return new Result(ResultCode.SUCCESS, deviceRepo.findAll(sf, pageable));
    }

    /**
     * @Method      : getCountDeviceFailureRate
     * @Description : 计算设备故障率
     * @Params      : [farmId, bit]
     * @Return      : com.huimv.common.utils.Result
     *
     * @Author      : ZhuoNing
     * @Date        : 2021/12/8
     * @Time        : 23:51
     */
    @Override
    public Result getCountDeviceFailureRate(Integer farmId, Integer bit) {
        if (bit == null || bit == 0) {
            bit = 2;
        }
        //获取设备总数
        List<Object[]> objList = deviceRepo.findDeviceTotal(farmId);
        Object[] totalObj = (Object[]) objList.get(0);
        int total = Integer.parseInt(totalObj[0].toString());
        System.out.println("total="+total);
        //获取有故障设备数
        Integer failureState = 2;
        List<Object[]> failureList = deviceRepo.findFailureDeviceTotal(farmId, failureState);
        Object[] failureObj = (Object[]) failureList.get(0);
        int num = Integer.parseInt(failureObj[0].toString());
        if (total == 0) {
            return new Result(10002, "当前该牧场无任何设备.", false);
        }
        String rate = mathUtil.countRate(num, total, bit);
        JSONObject outJo = new JSONObject();
        outJo.put("total",total+" 个");
        outJo.put("num",num+" 个");
        outJo.put("rate",rate+" %");
        return new Result(ResultCode.SUCCESS,outJo);
    }


}
