package com.huashe.park.common.geo;

import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public final class CoordinateUtil {
    // 2000坐标转wgs84坐标
    public static Double[] getCoordinate(Double x, Double y) {
        Double[] res = new Double[2];
        Coordinate tar = null;
        try {
            // 封装点，这个是通用的，也可以用POINT（y,x）
            // private static WKTReader reader = new WKTReader( geometryFactory );
            Coordinate sour = new Coordinate(y, x);
            // 这里要选择转换的坐标系是可以随意更换的
            CoordinateReferenceSystem source = CRS.decode("EPSG:4549");
            CoordinateReferenceSystem target = CRS.decode("EPSG:4326");
            // 建立转换，下面两个我屏掉的转换方式会报出需要3/7参数的异常
            // MathTransform mathTransform = CRS.findMathTransform(source, target);
            // MathTransform mathTransform1 = CRS.findMathTransform(source, target, false);
            MathTransform transform = CRS.findMathTransform(source, target, true);
            tar = new Coordinate();
            // 转换
            JTS.transform(sour, tar, transform);
        }
        catch (FactoryException | org.opengis.referencing.operation.TransformException e) {
            e.printStackTrace();
        }
        String[] split = (tar.toString().substring(1, tar.toString().length() - 1)).split(",");
        // 经纬度精度
        DecimalFormat fm = new DecimalFormat("0.0000000");
        res[0] = Double.valueOf(fm.format(Double.valueOf(split[0])));
        res[1] = Double.valueOf(fm.format(Double.valueOf(split[1])));
        return res;
    }

    /**
     * wgs84坐标转2000坐标
     * 
     * @param B 纬度
     * @param L 经度
     * @param degree 角度，即所用的地图是几度的，列如CGCS2000_3_Degree_GK_CM_120E 表示该地 图是3度的
     * @return
     */
    private Map<String, Double> GetXY(double B, double L, double degree) {
        Map<String, Double> map = new HashMap<>();
        double[] xy = new double[] {
            0.0D, 0.0D
        };
        double a = 6378137.0D;
        double b = 6356752.314245179D;
        double e = 0.081819190842621D;
        double eC = 0.0820944379496957D;
        double L0 = 0.0D;
        int n;
        if (degree == 6.0D) {
            n = (int) Math.round((L + degree / (double) 2) / degree);
            L0 = degree * (double) n - degree / (double) 2;
        }
        else {
            n = (int) Math.round(L / degree);
            L0 = degree * (double) n;
        }

        double radB = B * 3.141592653589793D / (double) 180;
        double radL = L * 3.141592653589793D / (double) 180;
        double deltaL = (L - L0) * 3.141592653589793D / (double) 180;
        double N = a * a / b / Math.sqrt((double) 1 + eC * eC * Math.cos(radB) * Math.cos(radB));
        double C1 = 1.0D + 0.75D * e * e + 0.703125D * Math.pow(e, 4.0D) + 0.68359375D * Math.pow(e, 6.0D)
            + 0.67291259765625D * Math.pow(e, 8.0D);
        double C2 = 0.75D * e * e + 0.9375D * Math.pow(e, 4.0D) + 1.025390625D * Math.pow(e, 6.0D)
            + 1.07666015625D * Math.pow(e, 8.0D);
        double C3 = 0.234375D * Math.pow(e, 4.0D) + 0.41015625D * Math.pow(e, 6.0D)
            + 0.538330078125D * Math.pow(e, 8.0D);
        double C4 = 0.068359375D * Math.pow(e, 6.0D) + 0.15380859375D * Math.pow(e, 8.0D);
        double C5 = 0.00240325927734375D * Math.pow(e, 8.0D);
        double t = Math.tan(radB);
        double eta = eC * Math.cos(radB);
        double X = a * ((double) 1 - e * e)
            * (C1 * radB - C2 * Math.sin((double) 2 * radB) / (double) 2 + C3 * Math.sin((double) 4 * radB) / (double) 4
                - C4 * Math.sin((double) 6 * radB) / (double) 6 + C5 * Math.sin((double) 8 * radB));
        xy[0] = X + N * Math.sin(radB) * Math.cos(radB) * Math.pow(deltaL, 2.0D)
            * ((double) 1
                + Math.pow(deltaL * Math.cos(radB), 2.0D)
                    * ((double) 5 - t * t + (double) 9 * eta * eta + (double) 4 * Math.pow(eta, 4.0D)) / (double) 12
                + Math.pow(deltaL * Math.cos(radB), 4.0D) * ((double) 61 - (double) 58 * t * t + Math.pow(t, 4.0D))
                    / (double) 360)
            / (double) 2;
        xy[1] = N * deltaL * Math.cos(radB)
            * ((double) 1 + Math.pow(deltaL * Math.cos(radB), 2.0D) * ((double) 1 - t * t + eta * eta) / (double) 6
                + Math.pow(deltaL * Math.cos(radB), 4.0D) * ((double) 5 - (double) 18 * t * t + Math.pow(t, 4.0D)
                    - (double) 14 * eta * eta - (double) 58 * eta * eta * t * t) / (double) 120)
            + (double) 500000;
        // return "纬度Y:"+xy[0]+"---经度X"+xy[1];
        map.put("X", xy[1]);
        map.put("Y", xy[0]);
        return map;
    }

    // 度分秒地理位置转wgs84坐标
    private String getPosition(String position) {
        String[] degree = position.split("\\°");
        if (degree.length == 1) {
            return position;
        }
        String d = degree[0];
        String[] one = degree[1].split("\\′");
        String a = one[0];
        if (!a.contains(".")) {
            if (a.substring(0, 1).equals("0")) {
                a = a.substring(1);
            }
        }
        else if (a.contains(".") && a.split("\\.").length > 1) {
            a = a.substring(1);
        }
        String[] two = one[1].split("\\″");
        String b = two[0];
        if (!b.contains(".")) {
            if (b.substring(0, 1).equals("0")) {
                b = b.substring(1);
            }
        }
        else if (b.contains(".") && b.split("\\.").length > 1) {
            if (b.substring(0, 1).equals("0")) {
                b = b.substring(1);
            }
        }
        BigDecimal fen = new BigDecimal(a);
        BigDecimal miao = new BigDecimal(b);
        BigDecimal du = new BigDecimal(d);
        // float f = Float.valueOf(a)+ Float.valueOf(Float.valueOf(b)/60);
        // float du = Float.valueOf(f/60)+Float.valueOf(d);
        BigDecimal add = fen.add(miao.divide(new BigDecimal("60"), 6, BigDecimal.ROUND_HALF_UP))
            .divide(new BigDecimal("60"), 6, BigDecimal.ROUND_HALF_UP).add(du);
        return String.valueOf(add);
    }

    private boolean isDouble(String str1, String str2) {
        try {
            Double.parseDouble(str1);
            Double.parseDouble(str2);
            return true;
        }
        catch (NumberFormatException ex) {
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(getCoordinate(2833742.70380015070,582577.02485382770)));
    }
}
