package com.ruoyi.bst.area.utils;

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

import org.locationtech.jts.geom.Geometry;

import com.ruoyi.bst.area.domain.Area;
import com.ruoyi.bst.area.domain.AreaVO;
import com.ruoyi.bst.area.domain.vo.LocationAreaVO;
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
import com.ruoyi.bst.areaSub.utils.AreaSubUtil;
import com.ruoyi.common.utils.map.GeoUtils;

public class AreaUtil {


    // 是否在运营区内（0误差）
    public static boolean isInArea(Area area, BigDecimal longitude, BigDecimal latitude) {
        Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
        if (geometry == null) {
            return false;
        }
        return GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, BigDecimal.ZERO);
    }

    // 是否在运营区最小内边界
    public static boolean isInAreaMin(AreaVO area, BigDecimal longitude, BigDecimal latitude) {
        if (area == null) {
            return false;
        }
        Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
        if (geometry == null) {
            return false;
        }
        return GeoUtils.isInPolygonWithShorten(longitude, latitude, geometry, area.getBoundaryDistance());
    }

    // 是否在运营区最大外边界
    public static boolean isInAreaMax(AreaVO area, BigDecimal longitude, BigDecimal latitude) {
        if (area == null) {
            return false;
        }
        Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
        if (geometry == null) {
            return false;
        }
        return GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, area.getOutageDistance());
    }

    public static LocationAreaVO getLocationArea(BigDecimal lon, BigDecimal lat, AreaVO area, List<AreaSubVO> noRidingList) {
        if (lon == null || lat == null) {
            return null;
        }

        LocationAreaVO vo = new LocationAreaVO();

        // 是否在运营区内
        vo.setIsInArea(AreaUtil.isInArea(area, lon, lat));

        // 是否在运营区最小内边界
        vo.setIsInAreaMin(AreaUtil.isInAreaMin(area, lon, lat));

        // 是否在运营区最大外边界
        vo.setIsInAreaMax(AreaUtil.isInAreaMax(area, lon, lat));

        // 是否在禁行区内
        AreaSubVO inNoRidingArea = AreaSubUtil.getInAreaSub(noRidingList, lon, lat, area.getError());
        vo.setInNoRidingArea(inNoRidingArea);
        vo.setIsInNoRidingArea(inNoRidingArea != null);

        // 靠近运营区边界时的播报距离
        BigDecimal boundaryDistance = area.getBoundaryDistance();
        // 是否靠近禁行区
        AreaSubVO nearAreaSub = AreaSubUtil.getNearAreaSub(noRidingList, lon, lat, area.getError(), boundaryDistance);
        vo.setNearNoRidingArea(nearAreaSub);
        vo.setIsNearNoRidingArea(nearAreaSub != null);

        return vo;
    }

}
