package com.huashe.park.collect.event;

import static com.huashe.park.common.consts.RedisKey.DEPTH_PRESS_TIPS;
import static com.huashe.park.common.consts.RedisKey.PILE_MACHINE_MQTT;
import static com.huashe.park.common.consts.enums.ConsStatus.CONS_STATUS_00;
import static com.huashe.park.common.consts.enums.ConsStatus.CONS_STATUS_02;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson2.JSONObject;
import com.huashe.park.common.DateTimeUtil;
import com.huashe.park.common.consts.RedisKey;
import com.huashe.park.common.consts.enums.MachineStatus;
import com.huashe.park.core.redis.RedisProxy;
import com.huashe.park.core.service.IConsPileHoleInfoService;
import com.huashe.park.core.service.IPileHoleIndexRealtimeService;
import com.huashe.park.core.service.IPileMachineInfoService;
import com.huashe.park.domain.entity.ConsPileHoleInfo;
import com.huashe.park.domain.entity.MachineProcess;
import com.huashe.park.domain.entity.MachineProcessResult;
import com.huashe.park.domain.entity.PileHoleIndexRealtime;
import com.huashe.park.domain.entity.PileMachineInfo;

@Service
public class MachineRealtimeEventListener {

    @Autowired
    private IConsPileHoleInfoService consPileHoleInfoService;

    @Autowired
    private IPileMachineInfoService machineInfoService;

    @Autowired
    private IPileHoleIndexRealtimeService pileHoleIndexRealtimeService;

    @Autowired
    private IPileMachineInfoService pileMachineInfoService;

    @Autowired
    private RedisProxy redisProxy;

    public void handleConsProcess(MachineProcess message) {
        ConsPileHoleInfo consPileHoleInfo = consPileHoleInfoService.selectConsPileHoleInfoByteId(message.getPileId());
        PileMachineInfo pileMachineInfo = machineInfoService.selectPileMachineInfoByByteId(message.getMachineId());
        if (ObjectUtils.isEmpty(consPileHoleInfo) || ObjectUtils.isEmpty(pileMachineInfo)) {
            return;
        }
        PileHoleIndexRealtime pileHoleIndexRealtime = new PileHoleIndexRealtime();
        pileHoleIndexRealtime.setHoleId(consPileHoleInfo.getId());
        pileHoleIndexRealtime.setMachineId(pileMachineInfo.getId());
        pileHoleIndexRealtime.setHoleByteKey(consPileHoleInfo.getByteId());
        pileHoleIndexRealtime.setMachineByteKey(pileMachineInfo.getByteId());

        pileHoleIndexRealtime.setConsUnitId(consPileHoleInfo.getConsUnitId());
        pileHoleIndexRealtime.setHoleNum(consPileHoleInfo.getHoleNum());

        pileHoleIndexRealtime.setCurrent(message.getCurrent());
        pileHoleIndexRealtime.setDepth(message.getPileLength());
        pileHoleIndexRealtime.setSprayPressure(message.getSprayPressure());
        pileHoleIndexRealtime.setTiltAngle(message.getTiltAngle());
        pileHoleIndexRealtime.setForwardTiltAngle(message.getForwardTiltAngle());
        // 送带量
        pileHoleIndexRealtime.setSendSprayVolume(message.getSprayVolume());
        pileHoleIndexRealtime.setVerticalDeviation(message.getVerticalAngle());
        pileHoleIndexRealtime.setRealLat(message.getLatitude());
        pileHoleIndexRealtime.setRealLng(message.getLongitude());
        pileHoleIndexRealtime.setRealX(message.getRealX());
        pileHoleIndexRealtime.setRealY(message.getRealY());
        pileHoleIndexRealtime.setTenantId(consPileHoleInfo.getTenantId());
        int cnt = pileHoleIndexRealtimeService.updatePileHoleIndexRealtimeByHoleIdAndMachineId(pileHoleIndexRealtime);
        String pileRedisKey = String.format(RedisKey.PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId());
        if (!redisProxy.hasKey(pileRedisKey)) {
            redisProxy.putMapToHash(String.format(RedisKey.PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId()),
                generateMapTemplate(), 60 * 30);
        }
        if (cnt < 1) {
            pileHoleIndexRealtime.setStatus(CONS_STATUS_02.getCode());
            String dateFromMills = DateTimeUtil.getDateFromMills(message.getDataTime());
            pileHoleIndexRealtime.setStartTime(DateTimeUtil.parseDate(dateFromMills));
            pileHoleIndexRealtimeService.insertPileHoleIndexRealtime(pileHoleIndexRealtime);
            consPileHoleInfoService.updateConsPileHoleInfo(new ConsPileHoleInfo() {
                {
                    setId(consPileHoleInfo.getId());
                    setConsStatus(CONS_STATUS_02.getCode());
                }
            });
        }

        pileMachineInfoService.updatePileMachineInfo(new PileMachineInfo() {
            {
                setId(pileMachineInfo.getId());
                setLat(consPileHoleInfo.getLat());
                setLng(consPileHoleInfo.getLng());
                setStatus(MachineStatus.MACHINE_STATUS_00.getCode());
            }
        });
        // 处置各种最大值
        handleMaxProcess(message);
    }

    public void handleConsResult(MachineProcessResult message) {
        ConsPileHoleInfo consPileHoleInfo = consPileHoleInfoService.selectConsPileHoleInfoByteId(message.getPileId());
        PileMachineInfo pileMachineInfo = machineInfoService.selectPileMachineInfoByByteId(message.getMachineId());
        if (ObjectUtils.isEmpty(consPileHoleInfo) || ObjectUtils.isEmpty(pileMachineInfo)) {
            return;
        }
        PileHoleIndexRealtime pileHoleIndexRealtime = new PileHoleIndexRealtime();
        pileHoleIndexRealtime.setHoleId(consPileHoleInfo.getId());
        pileHoleIndexRealtime.setHoleByteKey(consPileHoleInfo.getByteId());
        pileHoleIndexRealtime.setMachineByteKey(pileMachineInfo.getByteId());
        pileHoleIndexRealtime.setMachineId(pileMachineInfo.getId());
        pileHoleIndexRealtime.setDepth(message.getPileLength());
        pileHoleIndexRealtime.setConsUnitId(consPileHoleInfo.getConsUnitId());
        pileHoleIndexRealtime.setHoleNum(consPileHoleInfo.getHoleNum());
        pileHoleIndexRealtime.setSprayVolume(message.getSprayVolume());
        pileHoleIndexRealtime.setVerticalDeviation(message.getVerticalDeviation());
        pileHoleIndexRealtime.setStatus(CONS_STATUS_00.getCode());
        pileHoleIndexRealtime.setTenantId(consPileHoleInfo.getTenantId());
        if (ObjectUtils.isNotEmpty(message.getEndTime())) {
            String dateFromMills = DateTimeUtil.getDateFromMills(message.getEndTime());
            pileHoleIndexRealtime.setEndTime(DateTimeUtil.parseDate(dateFromMills));
        }
        pileHoleIndexRealtime
            .setEndPress(getValue(message.getPileId(), PILE_MACHINE_MQTT.MQTT_TOPIC_PROCESS_MAX_PRESS));
        pileHoleIndexRealtime.setDepthPress(depthPressMap(message.getPileId()));
        int cnt = pileHoleIndexRealtimeService.updatePileHoleIndexRealtimeByHoleIdAndMachineId(pileHoleIndexRealtime);
        if (cnt < 1) {
            String dateFromMills = DateTimeUtil.getDateFromMills(message.getStartTime());
            pileHoleIndexRealtime.setStartTime(DateTimeUtil.parseDate(dateFromMills));
            pileHoleIndexRealtimeService.insertPileHoleIndexRealtime(pileHoleIndexRealtime);
        }
        consPileHoleInfoService.updateConsPileHoleInfo(new ConsPileHoleInfo() {
            {
                setId(consPileHoleInfo.getId());
                setConsStatus(CONS_STATUS_00.getCode());
            }
        });
        pileMachineInfoService.updatePileMachineInfo(new PileMachineInfo() {
            {
                setId(pileMachineInfo.getId());
                setStatus(MachineStatus.MACHINE_STATUS_00.getCode());
            }
        });
    }

    private void handleMaxProcess(MachineProcess message) {
        Float maxPress = redisProxy.getHash(String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId()),
            PILE_MACHINE_MQTT.MQTT_TOPIC_PROCESS_MAX_PRESS);
        Float maxDepth = redisProxy.getHash(String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId()),
            PILE_MACHINE_MQTT.MQTT_TOPIC_PROCESS_MAX_DEPTH);
        Float sprayPressure = message.getSprayPressure();
        // 如果压力大于最大压力，则更新最大压力
        if (sprayPressure > maxPress) {
            redisProxy.putHash(String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId()),
                PILE_MACHINE_MQTT.MQTT_TOPIC_PROCESS_MAX_PRESS, sprayPressure);
        }
        // 如果深度大于最大深度，则更新最大深度
        if (message.getPileLength() > maxDepth) {
            redisProxy.putHash(String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId()),
                PILE_MACHINE_MQTT.MQTT_TOPIC_PROCESS_MAX_DEPTH, message.getPileLength());
        }
        {
            // 获取当前深度对应的最大压力
            int index = (int) Math.floor(message.getPileLength() / 0.25f);
            Float maxDepthPress = redisProxy.getHash(
                String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId()), Integer.toString(index));
            if (maxDepthPress < sprayPressure) {
                redisProxy.putHash(String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, message.getPileId()),
                    Integer.toString(index), sprayPressure);
            }
        }
    }

    private <T> T getValue(String pileId, String key) {
        return redisProxy.getHash(String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, pileId), key);
    }

    private JSONObject depthPressMap(String pileId) {
        Map<String, Float> allHash = redisProxy.getAllHash(String.format(PILE_MACHINE_MQTT.MQTT_TOPIC_PREFIX, pileId));
        if (CollectionUtils.isEmpty(allHash)) {
            return null;
        }
        JSONObject result = new JSONObject(DEPTH_PRESS_TIPS.PILE_LENGTH_TIPS);
        Float press;
        fillDepthZeroPressMap(allHash);
        for (int i = 0; i <= DEPTH_PRESS_TIPS.PILE_LENGTH_TIPS; i += 1) {
            press = allHash.get(Integer.toString(i));
            result.put(String.format("%.2fm", i * 0.25), press);
        }
        return result;
    }

    private void fillDepthZeroPressMap(Map<String, Float> allHash) {
        int prevNonZeroIndex = -1;
        Float press;
        Float currentValue;
        for (int i = 0; i <= DEPTH_PRESS_TIPS.PILE_LENGTH_TIPS; i++) {
            press = allHash.get(Integer.toString(i));
            if (press > 0F) {
                currentValue = press;
                for (int j = prevNonZeroIndex + 1; j < i; j++) {
                    allHash.put(Integer.toString(j), currentValue);
                }
                prevNonZeroIndex = i;
            }
        }
    }

    private Map<String, Object> generateMapTemplate() {
        Map<String, Object> result = new HashMap<String, Object>() {
            {
                put(PILE_MACHINE_MQTT.MQTT_TOPIC_PROCESS_MAX_PRESS, 0F);
                put(PILE_MACHINE_MQTT.MQTT_TOPIC_PROCESS_MAX_DEPTH, 0F);
            }
        };
        for (int i = 0; i <= DEPTH_PRESS_TIPS.PILE_LENGTH_TIPS; i += 1) {
            result.put(Integer.toString(i), 0F);
        }
        return result;
    }
}
