package com.ruoyi.bst.areaSub.utils;

import java.math.BigDecimal;
import java.util.List;

import org.locationtech.jts.geom.Geometry;

import com.ruoyi.bst.areaSub.domain.AreaSubVO;
import com.ruoyi.bst.areaSub.domain.enums.AreaSubStatus;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.common.utils.map.GeoUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AreaSubUtil {

    /**
     * 获取定位所在的区域
     * @param areaSubList 区域列表
     * @param longitude 经度
     * @param latitude 纬度
     * @param areaError 运营区误差
     * @return 最近的区域
     */
    public static AreaSubVO getInAreaSub(List<AreaSubVO> areaSubList, BigDecimal longitude, BigDecimal latitude, BigDecimal areaError) {
        if (CollectionUtils.isEmptyElement(areaSubList)) {
            return null;
        }
        BigDecimal tolerance = BigDecimal.ZERO; // 误差距离
        if (areaError != null) {
            tolerance = areaError;
        }
        for (AreaSubVO area : areaSubList) {
            Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
            if (geometry == null) {
                continue;
            }
            if (AreaSubStatus.DISABLED.getCode().equals(area.getStatus())) {
                continue;
            }
            if(area.getError() != null ){
                tolerance = area.getError();
            }
            boolean inCircle = GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, tolerance);
            if (inCircle) {
                return area;
            }
        }
        return null;
    }

    /**
     * 获取靠近的区域，而非是在区域内
     * @param areaSubList 区域列表
     * @param longitude 经度
     * @param latitude 纬度
     * @param distance 靠近多少
     * @return 靠近的区域
     */
    public static AreaSubVO getNearAreaSub(List<AreaSubVO> areaSubList, BigDecimal longitude, BigDecimal latitude, BigDecimal areaError, BigDecimal distance) {
        if (CollectionUtils.isEmptyElement(areaSubList)) {
            return null;
        }
        BigDecimal tolerance = BigDecimal.ZERO; // 误差距离
        if (areaError != null) {
            tolerance = areaError;
        }
        for (AreaSubVO area : areaSubList) {
            Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
            if (geometry == null) {
                continue;
            }
            if (AreaSubStatus.DISABLED.getCode().equals(area.getStatus())) {
                continue;
            }
            if (area.getError() != null) {
                tolerance = area.getError();
            }
            boolean inMax = GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, distance);    // 在外侧误差范围内
            boolean inCircle = GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, tolerance);   // 在内部
            // 不在内部，但在外侧误差范围内，视为靠近
            if (!inCircle && inMax) {
                return area;
            }
        }
        return null;
    }

}
