package com.huashe.park.application.engine.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate;
import org.apache.commons.lang3.ObjectUtils;
import org.locationtech.jts.geom.Polygon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONPath;
import com.huashe.park.application.engine.EvtFusionEngine;
import com.huashe.park.application.engine.LocationInfo;
import com.huashe.park.common.DateTimeUtil;
import com.huashe.park.common.consts.BDConst;
import com.huashe.park.common.geo.GeoUtils;
import com.huashe.park.core.redis.RedisProxy;
import com.huashe.park.core.service.IBdCameraInfoService;
import com.huashe.park.domain.dto.VideoFence;
import com.huashe.park.infrastructure.cfg.mqtt.MqttCfg;
import com.huashe.park.infrastructure.socket.server.UwbVideoTraceSocketServer;

import cn.hutool.core.lang.UUID;

/**
 * The type Room break in engine.
 */
@Service
@ConditionalOnBean(MqttClientTemplate.class)
@ConditionalOnProperty(name = "evt-fusion.video-trail-engine.enable", havingValue = "true")
public class VideoTrailEngine extends EvtFusionEngine {
    private static final Logger logger = LoggerFactory.getLogger(VideoTrailEngine.class);

    @Autowired
    private IBdCameraInfoService cameraInfoService;

    @Resource
    private RedisProxy redisService;

    @Value("${evt-fusion.fusion-time.video-trail:300}")
    private int MAX_EVT_TIME_GAP;

    @Resource
    private UwbVideoTraceSocketServer videoTraceSocketServer;

    private final List<LinkedBlockingQueue<JSONObject>> messageQueueList = new ArrayList<>(5);

    @PostConstruct
    public void init() {
        super.init();
        this.setEngineName("视频跟随");
        if (!redisService.hasKey(BDConst.REDIS_KEY.FENCE_VIDEO_TRACE)) {
            List<VideoFence> bdFenceInfos = cameraInfoService.selectBdCameraFence();
            if (CollectionUtils.isEmpty(bdFenceInfos)) {
                return;
            }
            bdFenceInfos.removeIf(item -> ObjectUtils.isEmpty(item.getPoly())
                || ObjectUtils.isEmpty(GeoUtils.getPolygon(item.getPoly())));
            redisService.setCacheList(BDConst.REDIS_KEY.FENCE_VIDEO_TRACE, bdFenceInfos);
        }
    }

    @Override
    public Boolean check(LocationInfo older, LocationInfo newer) {
        // long gap = newer.getSrcTimestamp() - older.getSrcTimestamp();
        // // 将gap 转换为秒
        // gap = gap / 1000;
        //
        // String oldFenceId = older.getMsg().getString("fenceId");
        // String newerFenceId = newer.getMsg().getString("fenceId");
        // logger.info("视频轨迹: {}, {},{}", older, newer, gap <= MAX_EVT_TIME_GAP && oldFenceId.equals(newerFenceId));
        return false;
    }

    @Override
    public List<LinkedBlockingQueue<JSONObject>> getQueue() {
        return messageQueueList;
    }

    /**
     * Gets key. 获取融合对象在redis中的key
     *
     * @param msg the msg
     * @return the key
     * @author chen.cheng
     */
    @Override
    public String getKey(LocationInfo msg) {
        return String.format("%s%s-%s", BDConst.REDIS_KEY.FENCE_VIDEO_TRACE_KEY, msg.getMsg().getString("key"),
            msg.getMsg().getString("fenceId"));
    }

    @Override
    public void getBizId(LocationInfo msg) {
        msg.setBizId(UUID.fastUUID().toString());
    }

    @Override
    public void newEvtCallback(LocationInfo msg) {
        videoTraceSocketServer.sendMessage(msg.getMsg().getString("tagId"), JSONObject.from(msg));
    }

    public void trailTag(JSONObject msg) {
        List<VideoFence> cacheList = redisService.getCacheList(BDConst.REDIS_KEY.FENCE_VIDEO_TRACE);
        if (CollectionUtils.isEmpty(cacheList)) {
            return;
        }
        Polygon polygon;
        HashMap<String, Object> video;
        JSONObject location;
        JSONObject properties = (JSONObject) JSONPath.eval(msg, "$.data.features[0].properties");
        for (VideoFence fenceInfo : cacheList) {
            polygon = GeoUtils.getPolygon(fenceInfo.getPoly());
            String tagId = properties.getString("tag_id");
            if (GeoUtils.isPointInGeoFence(polygon, properties.getString("pos_x"), properties.getString("pos_y"))) {
                location = new JSONObject();
                location.put("fenceId", fenceInfo.getId());
                location.put("fenceName", fenceInfo.getDefenceName());
                location.put("key", tagId);
                location.put("srcTimestamp", DateTimeUtil.timestampMillis());
                location.put("longitude", properties.getString("pos_x"));
                location.put("latitude", properties.getString("pos_y"));
                video = new HashMap<>();
                video.put("cameraName", fenceInfo.getCameraName());
                video.put("cameraStream", fenceInfo.getCameraStream());
                video.put("cameraLive", fenceInfo.getLiveStream());
                location.put("video", video);
                push(location);
                break;
            }
        }
    }
}
