package cn.com.taiji.track.listener;

import cn.com.taiji.track.dto.FocusTrackQueryDTO;
import cn.com.taiji.track.dto.IGeomesaTrackDTO;
import cn.com.taiji.track.entity.FocusShipEntity;
import cn.com.taiji.track.event.ChannelRemoveEvent;
import cn.com.taiji.track.event.EventType;
import cn.com.taiji.track.event.FocusTrackChannelAddEvent;
import cn.com.taiji.track.handler.HistoryTrackHandler;
import cn.com.taiji.track.service.IBeidouTrackService;
import cn.com.taiji.track.service.IFocusShipService;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.geotools.data.FeatureReader;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.filter.text.cql2.CQL;
import org.geotools.filter.text.cql2.CQLException;
import org.geotools.filter.text.ecql.ECQL;
import org.locationtech.geomesa.redis.data.RedisDataStore;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author chenfangchao
 * @title: BeidouChannelListener
 * @projectName ax-geomesa-redis
 * @description: TODO
 * @date 2022/9/22 6:00 PM
 */
@Component
@Slf4j
public class FocusTrackChannelListener {
    @Autowired
    private HistoryTrackHandler historyTrackHandler;
    @Autowired
    private IBeidouTrackService beidouTrackService;
    @Autowired
    private IFocusShipService focusShipService;
    @Autowired
    private RedisDataStore redisDataStore;
    @Autowired
    private IGeomesaTrackDTO geomesaTrackDTO;

    private final ConcurrentHashMap<String, Thread> concurrentHashMap = new ConcurrentHashMap<String, Thread>();
    /**
     * 监听新增用户信道
     *
     * @param event
     */
    @EventListener
    public void listenerNettyAddChannel(FocusTrackChannelAddEvent event) {
        {
            log.info("当前需要创建的线程名称为 {}", event.getChannelId());

            Thread thread = concurrentHashMap.get(event.getChannelId().asLongText());
            if (null != thread) {
                thread.interrupt();
            }

            thread = new Thread(() -> {
                while (true) {
                    try {
                        if (Thread.currentThread().isInterrupted()) {
                            return;
                        }
                        queryFocusTrack(event);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        e.printStackTrace();
                        return;
                    } catch (CQLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }, event.getChannelId().asLongText());

            thread.start();
            concurrentHashMap.put(event.getChannelId().asLongText(), thread);
        }
    }
    /**
     * 查询
     */
    private void queryFocusTrack(FocusTrackChannelAddEvent event) throws CQLException, IOException {
        JSONArray datas = new JSONArray();
        AttributeKey<String> key = AttributeKey.valueOf("focus-track");
        String dtoStr = event.getCtx().attr(key).get();
        FocusTrackQueryDTO dto = JSONObject.parseObject(dtoStr, FocusTrackQueryDTO.class);
        if (null != dto) {
            QueryWrapper<FocusShipEntity> wrapper = new QueryWrapper();
            if(StringUtils.hasText(dto.getUserId())){
                wrapper.eq("user_id",dto.getUserId());
            }
            List<FocusShipEntity> entities = focusShipService.list(wrapper);
            FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
            List<Filter> filters = new ArrayList<>();
            if(entities != null) {
                for (FocusShipEntity input : entities) {
                    Filter filter = CQL.toFilter("deviceId = \'" + input.getDevideNo() + "\'");
                    filters.add(filter);
                }
                Filter filter = ff.or(filters);
                String cql = dto.getCql();
                String realCql = dto.getRealCql();
                if (StringUtils.hasText(cql)) {
                    Filter cqlFilter = CQL.toFilter(cql);
                    filter = ff.and(filter,cqlFilter);
                }if (StringUtils.hasText(realCql)) {
                    Filter realCqlFilter = ECQL.toFilter(realCql);
                    filter = ff.and(filter,realCqlFilter);
                }
                Query query = new Query(geomesaTrackDTO.getTypeName(), filter);
                query.setMaxFeatures(Integer.parseInt("2000"));
                FeatureReader<SimpleFeatureType, SimpleFeature> focusReader = redisDataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
                //判断是否存在
                while (focusReader.hasNext()) {
                    SimpleFeature feature = focusReader.next();
                    Collection<Property> properties = feature.getProperties();
                    cn.hutool.json.JSONObject obj = new cn.hutool.json.JSONObject();
                    properties.forEach(property -> {
                        Object value = property.getValue();
                        if (value instanceof Geometry) {
                            Geometry geometry = (Geometry) value;
                            value = geometry.toText();
                        }
                        obj.put(property.getName().toString(), value);
                    });
                    datas.add(obj);
                }
            }
        }
        historyTrackHandler.sendMsgToSpecifyChannel(event.getChannelId(), JSONUtil.toJsonStr(new EventType<>(datas, geomesaTrackDTO.getWsLayerName())));
    }

    /**
     * 监听移除用户信道
     *
     * @param event
     */
    @EventListener
    public void listenerNettyRemoveChannel(ChannelRemoveEvent event) {
        log.info("当前需要移除的线程名称为 {}", event.getChannelId());
        Thread thread = concurrentHashMap.get(event.getChannelId().asLongText());
        thread.interrupt();
        concurrentHashMap.remove(event.getChannelId().asLongText());
    }
}
