package cn.com.taiji.track.service.impl;

import cn.com.taiji.track.constants.WarningCodeConstants;
import cn.com.taiji.track.dto.BeidouShipLocationDTO;
import cn.com.taiji.track.dto.ContainsDTO;
import cn.com.taiji.track.dto.IGeomesaTrackDTO;
import cn.com.taiji.track.entity.BeidouLocationEntity;
import cn.com.taiji.track.entity.BeidouShipArchives;
import cn.com.taiji.track.entity.BeidouTrackEntity;
import cn.com.taiji.track.mapper.BeidouLocationMapper;
import cn.com.taiji.track.mapper.BeidouShipArchivesMapper;
import cn.com.taiji.track.mapper.WarningAreaMapper;
import cn.com.taiji.track.service.IBeidouLocationService;
import cn.com.taiji.track.service.IShipStatusService;
import cn.com.taiji.track.utils.LatLngUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.filter.identity.FeatureIdImpl;
import org.geotools.util.factory.Hints;
import org.locationtech.geomesa.redis.data.RedisDataStore;
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.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Description:
 * @Author: hujie@umisoft.cn
 * @Date: 2021/11/30 9:59 下午
 */
@Service
@Slf4j
public class BeidouLocationServiceImpl extends ServiceImpl<BeidouLocationMapper, BeidouLocationEntity> implements IBeidouLocationService {
    @Autowired
    protected IShipStatusService shipStatusService;

    private Map<String,String> locationMaps= new HashMap<>();
    private Vector<BeidouLocationEntity> locationEntities= new Vector<>();

    @Autowired
    private SimpleFeatureType sftLocation;
    @Autowired
    private RedisDataStore redisDataStore;
    @Autowired
    private IGeomesaTrackDTO geomesaLocationDTO;
    @Autowired
    private BeidouShipArchivesMapper shipArchivesMapper;
    @Autowired
    private WarningAreaMapper warningAreaMapper;

    @Override
    public void beidouDynamicShipToCache(List<ConsumerRecord<?, ?>> records){
        try {
            for (ConsumerRecord<?, ?> record : records) {
                Optional message = Optional.ofNullable(record.value());
                if (message.isPresent()) {
                    Object msg = message.get();
                    BeidouLocationEntity locationEntity = JSONObject.parseObject(msg.toString(), BeidouLocationEntity.class);
                    String location = StrUtil.format("POINT ({} {})", locationEntity.getLongitude(),locationEntity.getLatitude());
                    locationEntity.setLocation(location);
                    BigDecimal longitudeDecimal = new BigDecimal(locationEntity.getLongitude());
                    locationEntity.setLongitude(LatLngUtil.latLng2Dfm(longitudeDecimal.doubleValue()));
                    BigDecimal latitudeDecimal = new BigDecimal(locationEntity.getLatitude());
                    locationEntity.setLatitude(LatLngUtil.latLng2Dfm(latitudeDecimal.doubleValue()));
                    locationEntities.add(locationEntity);
                    shipStatusService.pushOnLineDeviceId(locationEntity.getDeviceId(),"true");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void cacheBeidouToMySql() {
        Date begin = new Date();
        if(locationEntities.size() > 0){
            List<BeidouLocationEntity> saveList = new ArrayList<>(locationEntities);
            locationEntities.clear();
            for(BeidouLocationEntity e : saveList){
                if(!StringUtils.hasText(e.getShipName())){
                    QueryWrapper<BeidouShipArchives> wrapper = new QueryWrapper();
                    wrapper.eq("devide_no",e.getDeviceId());
                    BeidouShipArchives shipArchives = shipArchivesMapper.selectOne(wrapper);
                    if(shipArchives!=null){
                        e.setShipName(shipArchives.getShipId());
                    }
                }
                String location = e.getLocation();
                if (StringUtils.hasText(location) && !location.equals(locationMaps.get(e.getDeviceId()))) {
//                if (StringUtils.hasText(location)) {
                    String longitude = location.substring(location.indexOf("(")+1,location.indexOf(" ",location.indexOf("(")));
                    String latitude = location.substring(location.indexOf(" ",location.indexOf("("))+1,location.indexOf(")"));
                    List<ContainsDTO> result = warningAreaMapper.containsPoint(longitude,latitude);
                    if(result.size()>0){
                        shipStatusService.pushinportDeviceId(e.getDeviceId(), WarningCodeConstants.INPORT_WARNING);
                    }else{
                        shipStatusService.pushinportDeviceId(e.getDeviceId(),WarningCodeConstants.OUTPROT_WARNING);
                    }
                    locationMaps.put(e.getDeviceId(),e.getLocation());
                }
            }
            saveBatch(saveList);
            log.info("位置数据写入数据库完成！耗时 {} 毫秒, 合计保存 {} 条记录", (new Date()).getTime() - begin.getTime(), saveList.size());
        }
    }

    @Override
    public void listLocationToCache() {
        Date begin = new Date();
        List<BeidouShipLocationDTO> results = baseMapper.listLocation();
        if (results.size() > 0) {
            FeatureReader<SimpleFeatureType, SimpleFeature> reader = null;
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = null;
            try {
                writer = redisDataStore.getFeatureWriterAppend(sftLocation.getTypeName(), Transaction.AUTO_COMMIT);
                SimpleFeatureBuilder builder = new SimpleFeatureBuilder(sftLocation);
                for (IGeomesaTrackDTO dto : results) {
                    dto.setKafkaConsumerGroup(geomesaLocationDTO.getKafkaConsumerGroup());
                    dto.setExpirySeconds(geomesaLocationDTO.getExpirySeconds());
                    if (!dto.checkPoint()) {
                        continue;
                    }
                    String fid = dto.getFid();
                    boolean append = true;
                    FilterFactory2 filterFactory = CommonFactoryFinder.getFilterFactory2();
                    Filter filter = null;
                    if (null != fid && !"".equals(fid)) {
                        filter = filterFactory.id(filterFactory.featureId(fid));
                    } else {
                        String id = UUID.randomUUID().toString();
                        filter = filterFactory.id(filterFactory.featureId(id));
                    }
                    Query query = new Query(dto.getTypeName(), filter);
                    reader = redisDataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
                    if (reader.hasNext()) {
                        append = false;
                        SimpleFeature feature=reader.next();
                        String locationTime = feature.getAttribute("locationTime").toString();
                        if(!locationTime.equals(String.valueOf(dto.getValueList()[6]))){
                            String[] propList = dto.getPropList();
                            Object[] valueList = dto.getValueList();
                            redisDataStore.getFeatureSource(dto.getTypeName()).modifyFeatures(propList, valueList, filter);
                        }
                    }
                    reader.close();
                    reader = null;
                    if (append) {
                        SimpleFeature toWrite = writer.next();
                        builder.reset();
                        SimpleFeature feature = dto.toSimpleFeature(builder, fid);
                        toWrite.setAttributes(feature.getAttributes());
                        toWrite.getUserData().put(Hints.USE_PROVIDED_FID, Boolean.TRUE);
                        ((FeatureIdImpl) toWrite.getIdentifier()).setID(feature.getID());
                        toWrite.getUserData().putAll(feature.getUserData());
                        writer.write();
                    }
                }
            } catch (Exception e) {
                log.error("=======插入geomesa发生异常============");
                e.printStackTrace();
            } finally {
                try {
                    if (null != writer) {
                        writer.close();
                    }
                    if (null != reader) {
                        reader.close();
                    }
                } catch (Exception e) {
                    log.error("=======close操作发生异常============");
                    e.printStackTrace();
                }
            }
//            log.info("位置数据插入geomesa完成！耗时 {} 毫秒, 合计保存 {} 条记录", (new Date()).getTime() - begin.getTime(), results.size());
        }
    }
}
