package com.ruoyi.ibs.grid.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.ibs.grid.domain.entity.AdminDivision;
import com.ruoyi.ibs.grid.domain.entity.GridAreaFence;
import com.ruoyi.ibs.grid.mapper.AdminDivisionMapper;
import com.ruoyi.ibs.grid.mapper.GridAreaFenceMapper;
import com.ruoyi.ibs.grid.service.AddressAnalyseService;
import com.ruoyi.ibs.grid.service.GridAreaFenceService;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;
import org.locationtech.jts.operation.union.UnaryUnionOp;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author 吴凯程
 * @Date 2024/11/8
 **/
@Service
@Slf4j
public class GridAreaFenceServiceImpl implements GridAreaFenceService {

    @Resource
    private GridAreaFenceMapper gridAreaFenceMapper;

    @Resource
    private AdminDivisionMapper adminDivisionMapper;

    @Resource
    private AddressAnalyseService addressAnalyseService;

    private final WKTWriter writer = new WKTWriter();

    private final WKTReader reader = new WKTReader();

    /**
     * @param gridType
     * @param codeList
     * @return
     */
    @Override
    public Boolean updateGridFence(String gridType, Long gridId, List<String> codeList) {
        LambdaQueryWrapper<GridAreaFence> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GridAreaFence::getGridId, gridId)
                .eq(GridAreaFence::getGridType, gridType);
        GridAreaFence gridAreaFence = gridAreaFenceMapper.selectOne(queryWrapper);
        String unionWKT = getUnionWKT(codeList);
        if (Objects.isNull(gridAreaFence)) {
            gridAreaFence = new GridAreaFence();
            gridAreaFence.setGridId(gridId);
            gridAreaFence.setGridType(gridType);
            gridAreaFence.setFence(unionWKT);
            return gridAreaFenceMapper.insert(gridAreaFence) > 0;
        } else {
            gridAreaFence.setFence(unionWKT);
            return gridAreaFenceMapper.updateById(gridAreaFence) > 0;
        }
    }

    @Override
    public void deleteGridFence(String gridType, Long gridId) {
        LambdaQueryWrapper<GridAreaFence> queryWrapperFence = new LambdaQueryWrapper<>();
        queryWrapperFence.eq(GridAreaFence::getGridId, gridId).eq(GridAreaFence::getGridType, gridType);
        gridAreaFenceMapper.delete(queryWrapperFence);

    }

    /**
     * @param gridType
     * @param gridId
     * @return
     */
    @Override
    public Geometry getGeometry(String gridType, Long gridId) {
        LambdaQueryWrapper<GridAreaFence> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GridAreaFence::getGridId, gridId)
                .eq(GridAreaFence::getGridType, gridType);
        GridAreaFence gridAreaFence = gridAreaFenceMapper.selectOne(queryWrapper);
        if (Objects.isNull(gridAreaFence)) {
            throw new ServiceException("围栏数据不存在！");
        }
        try {
            return reader.read(gridAreaFence.getFence());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    private String getUnionWKT(List<String> codeList) {
        LambdaQueryWrapper<AdminDivision> queryWrapper1 = new LambdaQueryWrapper<>();
        codeList.forEach(code -> queryWrapper1.or().eq(AdminDivision::getCode, code));
        List<Integer> ids = adminDivisionMapper.selectList(queryWrapper1).stream().map(AdminDivision::getId).collect(Collectors.toList());
        List<Geometry> collect = ids.stream().map(id -> {
            Geometry geometryById = addressAnalyseService.getGeometryById(id);
            if (Objects.isNull(geometryById)) {
                log.info("缺少Geometry信息：" + id);
            }
            return geometryById;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        Geometry geometry = UnaryUnionOp.union(collect);
        return writer.write(geometry);
    }


}
