package com.ruoyi.dataprocess.amap;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;

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

public class PositionUtils {

    /**
     * @return boolean
     * @param: locationVo 区域
     * @param: lng 要判断的点的经度
     * @param: lat 要判断的点的纬度
     * @description 判断定位是否在区域LocationVo内
     * @author xins
     * @date 2023-09-02 12:47
     */
    public static boolean checkAddressInLocation(LocationVo locationVo, Double lng, Double lat) {
        if (locationVo == null) {
            return false;
        }
        if (lng != null && lat != null && lng.compareTo(0.000000000000) > 0 && lat.compareTo(0.000000000000) > 0) {
            if (locationVo.getMarkerType() == LocationVo.MARKER_TYPE_CIRCULAR) {//如果是圆
                double distance =  calculateLineDistance(lng,lat,locationVo.getLongitude(), locationVo.getLatitude());
                System.out.println("dis:"+distance);
                return (distance - locationVo.getRadius()) <=0;
            } else if (locationVo.getMarkerType() == LocationVo.MARKER_TYPE_POLYGON) {
                //多个多边形点集合字符串
                List<List<PositionVo>> coordinates = locationVo.getPolygonList();
                if (coordinates == null || coordinates.isEmpty()) {
                    return false;
                }
                //可以传好几个多边形
                for (List<PositionVo> positionVos : coordinates) {
                    Coordinate[] coordinates1 = new Coordinate[positionVos.size() + 1];
                    for (int i = 0; i < positionVos.size(); i++) {
                        BigDecimal longitudeB = positionVos.get(i).getLongitude();
                        BigDecimal latitudeB = positionVos.get(i).getLatitude();
                        if (longitudeB == null || latitudeB == null) {//数据异常
                            return false;
                        }

                        Double longitude = longitudeB.doubleValue();
                        Double latitude = latitudeB.doubleValue();

                        Coordinate coordinate = new Coordinate(longitude, latitude);
                        coordinates1[i] = coordinate;
                    }
                    //是起点也是终点
                    coordinates1[positionVos.size()] = new Coordinate(positionVos.get(0).getLongitude().doubleValue(),
                            positionVos.get(0).getLatitude().doubleValue());
                    if (isPointInPolygon(lat.doubleValue(), lng.doubleValue(), coordinates1)) {
                        return true;//只需要定位在其中一个的多边形范围内
                    }
                }
                return false;
            }
            return false;
        } else {
            return false;
        }
    }


//    public static boolean checkWithinTheCircula(LocationVo circulaVo, Double lng, Double lat) {//判断点与圆心之间的距离和圆半径的关系
//
//        System.out.println(lng.subtract(circulaVo.getLongitude()).doubleValue());
//        System.out.println(lat.subtract(circulaVo.getLatitude()).doubleValue());
//        double d2 = Math.hypot(lng.subtract(circulaVo.getLongitude()), lat.subtract(circulaVo.getLatitude()).doubleValue());
//
//        System.out.println("d2==" + d2);
//
//        double r = circulaVo.getRadius();
//        //圆外
//        if (d2 > r) {
//            return false;
//        } else {//圆内或圆上
//            return true;
//        }
//    }

    /**
     * 判断坐标之间的距离
     * （高德地图Android库的反编译源码）
     *
     * @param longitude 待判断经度
     * @param latitude  待判断纬度
     * @param centerLon 中心点经度
     * @param centerLat 中心点纬度
     * @return 返回的距离，单位米
     */
    public static Double calculateLineDistance(double longitude, double latitude, double centerLon, double centerLat) {
        if (longitude == 0 || latitude == 0 || centerLat == 0 || centerLon == 0) {
            return -1.0;
        }
        longitude *= 0.01745329251994329;
        latitude *= 0.01745329251994329;
        centerLon *= 0.01745329251994329;
        centerLat *= 0.01745329251994329;
        double var10 = Math.sin(longitude);
        double var12 = Math.sin(latitude);
        double var14 = Math.cos(longitude);
        double var16 = Math.cos(latitude);
        double var18 = Math.sin(centerLon);
        double var20 = Math.sin(centerLat);
        double var22 = Math.cos(centerLon);
        double var24 = Math.cos(centerLat);
        double[] var28 = new double[3];
        double[] var29 = new double[3];
        var28[0] = var16 * var14;
        var28[1] = var16 * var10;
        var28[2] = var12;
        var29[0] = var24 * var22;
        var29[1] = var24 * var18;
        var29[2] = var20;
        double distance = Math.asin(Math.sqrt((var28[0] - var29[0]) * (var28[0] - var29[0]) + (var28[1] - var29[1]) * (var28[1] - var29[1]) + (var28[2] - var29[2]) * (var28[2] - var29[2])) / 2.0) * 1.27420015798544E7;
        return distance;
    }


    /**
     * 判断是否在多边形区域内
     *
     * @param latitude           经度
     * @param longitude          纬度
     * @param polygonCoordinates 多边形点集合
     * @return
     */
    public static boolean isPointInPolygon(double latitude, double longitude, Coordinate[] polygonCoordinates) {
        GeometryFactory geometryFactory = new GeometryFactory();
        Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude));
        Polygon polygon = geometryFactory.createPolygon(polygonCoordinates);

        return polygon.touches(point) || polygon.contains(point);
    }


    public static void main(String[] args) {
        LocationVo locationVo = new LocationVo();
        locationVo.setMarkerType(LocationVo.MARKER_TYPE_POLYGON);

        List<List<PositionVo>> polygonList = new ArrayList<>();
        List<PositionVo> postionList = new ArrayList<>();
        //林和西地铁站
        postionList.add(new PositionVo(new BigDecimal("113.323947"), new BigDecimal("23.141525")));
        //五羊邨地铁站
        postionList.add(new PositionVo(new BigDecimal(113.314119), new BigDecimal(23.119977)));
        //体育中心南地铁站
        postionList.add(new PositionVo(new BigDecimal(113.324247), new BigDecimal(23.134501)));
        //猎德地铁站
        postionList.add(new PositionVo(new BigDecimal(113.331972), new BigDecimal(23.118477)));
        polygonList.add(postionList);
        locationVo.setPolygonList(polygonList);


//        boolean check1 = checkAddressInLocation(locationVo,new BigDecimal(113.323239),new BigDecimal(23.135428));
//        System.out.println(check1);
//        check1 = checkAddressInLocation(locationVo,new BigDecimal(113.321522),new BigDecimal(23.13381));
//        System.out.println(check1);
//        check1 = checkAddressInLocation(locationVo,new BigDecimal(113.324462),new BigDecimal(23.127002));
//        System.out.println(check1);
//        check1 = checkAddressInLocation(locationVo,new BigDecimal(113.324247),new BigDecimal(23.116188));
//        System.out.println(check1);
//        check1 = checkAddressInLocation(locationVo,new BigDecimal(113.319773),new BigDecimal(23.121664));
//        System.out.println(check1);
//        check1 = checkAddressInLocation(locationVo,new BigDecimal(113.307757),new BigDecimal(23.127249));
//        System.out.println(check1);


        LocationVo circulrVo = new LocationVo();
        circulrVo.setRadius(9.0056);
        circulrVo.setLongitude(116.404172);
        circulrVo.setLatitude(39.916605);
        circulrVo.setMarkerType(LocationVo.MARKER_TYPE_CIRCULAR);

        boolean check2 = checkAddressInLocation(circulrVo, 116.404072, 39.916605);
        System.out.println(check2);

    }
}
