package cn.com.taiji.track.listener;

import cn.com.taiji.track.dto.IGeomesaTrackDTO;
import cn.com.taiji.track.event.ChannelAddEvent;
import cn.com.taiji.track.event.ChannelRemoveEvent;
import cn.com.taiji.track.event.EventType;
import cn.com.taiji.track.handler.WebSocketHandler;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
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.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.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author chenfangchao
 * @title: BeidouChannelListener
 * @projectName ax-geomesa-redis
 * @description: TODO
 * @date 2022/9/22 6:00 PM
 */
@Component
@Slf4j
public class ChannelListener {

    @Autowired
    private RedisDataStore redisDataStore;

    @Autowired
    private WebSocketHandler webSocketHandler;

    private final ConcurrentHashMap<String, Thread> concurrentHashMap = new ConcurrentHashMap<String, Thread>();

    @Autowired
    private IGeomesaTrackDTO geomesaTrackDTO;

    /**
     * 监听新增用户信道
     *
     * @param event
     */
    @EventListener
    public void listenerNettyAddChannel(ChannelAddEvent 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;
                    }
                    JSONArray datas = new JSONArray();

                    AttributeKey<String> key = AttributeKey.valueOf("cql");
                    String cql = event.getCtx().attr(key).get();
                    if (null != cql) {
                        //查询是否存在
                        Query query = new Query(geomesaTrackDTO.getTypeName(), ECQL.toFilter(cql));
//                        query.setMaxFeatures(Integer.parseInt("2000"));
                        FeatureReader<SimpleFeatureType, SimpleFeature> reader = redisDataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
                        //判断是否存在
                        while (reader.hasNext()) {
                            SimpleFeature feature = reader.next();
                            Collection<Property> properties = feature.getProperties();
                            JSONObject obj = new 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);
                        }
                    }

                    AttributeKey<String> key1 = AttributeKey.valueOf("realCql");
                    String realCql = event.getCtx().attr(key1).get();
                    if (null != realCql) {
                        Query realQuery = new Query(geomesaTrackDTO.getTypeName(), ECQL.toFilter(realCql));
//                        realQuery.setMaxFeatures(Integer.parseInt("2000"));
                        FeatureReader<SimpleFeatureType, SimpleFeature> realReader = redisDataStore.getFeatureReader(realQuery, Transaction.AUTO_COMMIT);
                        //判断是否存在
                        while (realReader.hasNext()) {
                            SimpleFeature feature = realReader.next();
                            Collection<Property> properties = feature.getProperties();
                            JSONObject obj = new 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);
                        }
                    }
                    webSocketHandler.sendMsgToSpecifyChannel(event.getChannelId(), JSONUtil.toJsonStr(new EventType<>(datas, geomesaTrackDTO.getWsLayerName())));
                    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);
    }


    /**
     * 监听移除用户信道
     *
     * @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());
    }


}
