//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.base.core.source;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class LatLon {
    public static final LatLon ZERO;
    public final Angle latitude;
    public final Angle longitude;

    static {
        ZERO = new LatLon(Angle.ZERO, Angle.ZERO);
    }

    public static LatLon fromRadians(double latitude, double longitude) {
        return new LatLon(Math.toDegrees(latitude), Math.toDegrees(longitude));
    }

    public static LatLon fromDegrees(double latitude, double longitude) {
        return new LatLon(latitude, longitude);
    }

    private LatLon(double latitude, double longitude) {
        this.latitude = Angle.fromDegrees(latitude);
        this.longitude = Angle.fromDegrees(longitude);
    }

    public LatLon(Angle latitude, Angle longitude) {
        if (latitude != null && longitude != null) {
            this.latitude = latitude;
            this.longitude = longitude;
        } else {
            throw new IllegalArgumentException("nullValue.LatitudeOrLongitudeIsNull");
        }
    }

    public LatLon(LatLon latLon) {
        if (latLon == null) {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        } else {
            this.latitude = latLon.latitude;
            this.longitude = latLon.longitude;
        }
    }

    public final Angle getLatitude() {
        return this.latitude;
    }

    public final Angle getLongitude() {
        return this.longitude;
    }

    public double[] asDegreesArray() {
        return new double[]{this.getLatitude().degrees, this.getLongitude().degrees};
    }

    public double[] asRadiansArray() {
        return new double[]{this.getLatitude().radians, this.getLongitude().radians};
    }

    public static Angle greatCircleDistance(LatLon p1, LatLon p2) {
        if (p1 != null && p2 != null) {
            double lat1 = p1.getLatitude().radians;
            double lon1 = p1.getLongitude().radians;
            double lat2 = p2.getLatitude().radians;
            double lon2 = p2.getLongitude().radians;
            if (lat1 == lat2 && lon1 == lon2) {
                return Angle.ZERO;
            } else {
                double a = Math.sin((lat2 - lat1) / 2.0D);
                double b = Math.sin((lon2 - lon1) / 2.0D);
                double c = a * a + Math.cos(lat1) * Math.cos(lat2) * b * b;
                double distanceRadians = 2.0D * Math.asin(Math.sqrt(c));
                return Double.isNaN(distanceRadians) ? Angle.ZERO : Angle.fromRadians(distanceRadians);
            }
        } else {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        }
    }

    public static Angle greatCircleAzimuth(LatLon p1, LatLon p2) {
        if (p1 != null && p2 != null) {
            double lat1 = p1.getLatitude().radians;
            double lon1 = p1.getLongitude().radians;
            double lat2 = p2.getLatitude().radians;
            double lon2 = p2.getLongitude().radians;
            if (lat1 == lat2 && lon1 == lon2) {
                return Angle.ZERO;
            } else if (lon1 == lon2) {
                return lat1 > lat2 ? Angle.POS180 : Angle.ZERO;
            } else {
                double y = Math.cos(lat2) * Math.sin(lon2 - lon1);
                double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
                double azimuthRadians = Math.atan2(y, x);
                return Double.isNaN(azimuthRadians) ? Angle.ZERO : Angle.fromRadians(azimuthRadians);
            }
        } else {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        }
    }

    public static LatLon greatCircleEndPosition(LatLon p, Angle greatCircleAzimuth, Angle pathLength) {
        if (p == null) {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        } else if (greatCircleAzimuth != null && pathLength != null) {
            double lat = p.getLatitude().radians;
            double lon = p.getLongitude().radians;
            double azimuth = greatCircleAzimuth.radians;
            double distance = pathLength.radians;
            if (distance == 0.0D) {
                return p;
            } else {
                double endLatRadians = Math.asin(Math.sin(lat) * Math.cos(distance) + Math.cos(lat) * Math.sin(distance) * Math.cos(azimuth));
                double endLonRadians = lon + Math.atan2(Math.sin(distance) * Math.sin(azimuth), Math.cos(lat) * Math.cos(distance) - Math.sin(lat) * Math.sin(distance) * Math.cos(azimuth));
                return !Double.isNaN(endLatRadians) && !Double.isNaN(endLonRadians) ? new LatLon(Angle.fromRadians(endLatRadians).normalizedLatitude(), Angle.fromRadians(endLonRadians).normalizedLongitude()) : p;
            }
        } else {
            throw new IllegalArgumentException("nullValue.AngleIsNull");
        }
    }

    public static LatLon greatCircleEndPosition(LatLon p, double greatCircleAzimuthRadians, double pathLengthRadians) {
        if (p == null) {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        } else {
            return greatCircleEndPosition(p, Angle.fromRadians(greatCircleAzimuthRadians), Angle.fromRadians(pathLengthRadians));
        }
    }

    public static LatLon[] greatCircleExtremeLocations(LatLon location, Angle azimuth) {
        if (location == null) {
            throw new IllegalArgumentException("nullValue.LocationIsNull");
        } else if (azimuth == null) {
            throw new IllegalArgumentException("nullValue.AzimuthIsNull");
        } else {
            double lat0 = location.getLatitude().radians;
            double az = azimuth.radians;
            double tanDistance = -Math.tan(lat0) / Math.cos(az);
            double distance = Math.atan(tanDistance);
            Angle extremeDistance1 = Angle.fromRadians(distance + 1.5707963267948966D);
            Angle extremeDistance2 = Angle.fromRadians(distance - 1.5707963267948966D);
            return new LatLon[]{greatCircleEndPosition(location, azimuth, extremeDistance1), greatCircleEndPosition(location, azimuth, extremeDistance2)};
        }
    }

    public static LatLon[] greatCircleArcExtremeLocations(LatLon begin, LatLon end) {
        if (begin == null) {
            throw new IllegalArgumentException("nullValue.BeginIsNull");
        } else if (end == null) {
            throw new IllegalArgumentException("nullValue.EndIsNull");
        } else {
            LatLon minLatLocation = null;
            LatLon maxLatLocation = null;
            double minLat = Angle.POS90.degrees;
            double maxLat = Angle.NEG90.degrees;
            Iterator var9 = Arrays.asList(begin, end).iterator();

            while(var9.hasNext()) {
                LatLon ll = (LatLon)var9.next();
                if (minLat >= ll.getLatitude().degrees) {
                    minLat = ll.getLatitude().degrees;
                    minLatLocation = ll;
                }

                if (maxLat <= ll.getLatitude().degrees) {
                    maxLat = ll.getLatitude().degrees;
                    maxLatLocation = ll;
                }
            }

            Angle greatArcAzimuth = greatCircleAzimuth(begin, end);
            Angle greatArcDistance = greatCircleDistance(begin, end);
            LatLon[] greatCircleExtremes = greatCircleExtremeLocations(begin, greatArcAzimuth);
            LatLon[] var14 = greatCircleExtremes;
            int var13 = greatCircleExtremes.length;

            for(int var12 = 0; var12 < var13; ++var12) {
                LatLon ll = var14[var12];
                Angle az = greatCircleAzimuth(begin, ll);
                Angle d = greatCircleDistance(begin, ll);
                if (Math.signum(az.degrees) == Math.signum(greatArcAzimuth.degrees) && d.degrees >= 0.0D && d.degrees <= greatArcDistance.degrees) {
                    if (minLat >= ll.getLatitude().degrees) {
                        minLat = ll.getLatitude().degrees;
                        minLatLocation = ll;
                    }

                    if (maxLat <= ll.getLatitude().degrees) {
                        maxLat = ll.getLatitude().degrees;
                        maxLatLocation = ll;
                    }
                }
            }

            return new LatLon[]{minLatLocation, maxLatLocation};
        }
    }

    public static LatLon[] greatCircleArcExtremeLocations(Iterable<? extends LatLon> locations) {
        if (locations == null) {
            throw new IllegalArgumentException("nullValue.LocationsListIsNull");
        } else {
            LatLon minLatLocation = null;
            LatLon maxLatLocation = null;
            LatLon lastLocation = null;
            Iterator var5 = locations.iterator();

            while(true) {
                LatLon ll;
                while(true) {
                    if (!var5.hasNext()) {
                        return new LatLon[]{minLatLocation, maxLatLocation};
                    }

                    ll = (LatLon)var5.next();
                    if (lastLocation == null) {
                        break;
                    }

                    LatLon[] extremes = greatCircleArcExtremeLocations(lastLocation, ll);
                    if (extremes != null) {
                        if (minLatLocation == null || minLatLocation.getLatitude().degrees > extremes[0].getLatitude().degrees) {
                            minLatLocation = extremes[0];
                        }

                        if (maxLatLocation == null || maxLatLocation.getLatitude().degrees < extremes[1].getLatitude().degrees) {
                            maxLatLocation = extremes[1];
                        }
                        break;
                    }
                }

                lastLocation = ll;
            }
        }
    }

    public static Angle rhumbDistance(LatLon p1, LatLon p2) {
        if (p1 != null && p2 != null) {
            double lat1 = p1.getLatitude().radians;
            double lon1 = p1.getLongitude().radians;
            double lat2 = p2.getLatitude().radians;
            double lon2 = p2.getLongitude().radians;
            if (lat1 == lat2 && lon1 == lon2) {
                return Angle.ZERO;
            } else {
                double dLat = lat2 - lat1;
                double dLon = lon2 - lon1;
                double dPhi = Math.log(Math.tan(lat2 / 2.0D + 0.7853981633974483D) / Math.tan(lat1 / 2.0D + 0.7853981633974483D));
                double q = dLat / dPhi;
                if (Double.isNaN(dPhi) || Double.isNaN(q)) {
                    q = Math.cos(lat1);
                }

                if (Math.abs(dLon) > 3.141592653589793D) {
                    dLon = dLon > 0.0D ? -(6.283185307179586D - dLon) : 6.283185307179586D + dLon;
                }

                double distanceRadians = Math.sqrt(dLat * dLat + q * q * dLon * dLon);
                return Double.isNaN(distanceRadians) ? Angle.ZERO : Angle.fromRadians(distanceRadians);
            }
        } else {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        }
    }

    public static Angle rhumbAzimuth(LatLon p1, LatLon p2) {
        if (p1 != null && p2 != null) {
            double lat1 = p1.getLatitude().radians;
            double lon1 = p1.getLongitude().radians;
            double lat2 = p2.getLatitude().radians;
            double lon2 = p2.getLongitude().radians;
            if (lat1 == lat2 && lon1 == lon2) {
                return Angle.ZERO;
            } else {
                double dLon = lon2 - lon1;
                double dPhi = Math.log(Math.tan(lat2 / 2.0D + 0.7853981633974483D) / Math.tan(lat1 / 2.0D + 0.7853981633974483D));
                if (Math.abs(dLon) > 3.141592653589793D) {
                    dLon = dLon > 0.0D ? -(6.283185307179586D - dLon) : 6.283185307179586D + dLon;
                }

                double azimuthRadians = Math.atan2(dLon, dPhi);
                return Double.isNaN(azimuthRadians) ? Angle.ZERO : Angle.fromRadians(azimuthRadians);
            }
        } else {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        }
    }

    public static LatLon rhumbEndPosition(LatLon p, Angle rhumbAzimuth, Angle pathLength) {
        if (p == null) {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        } else if (rhumbAzimuth != null && pathLength != null) {
            double lat1 = p.getLatitude().radians;
            double lon1 = p.getLongitude().radians;
            double azimuth = rhumbAzimuth.radians;
            double distance = pathLength.radians;
            if (distance == 0.0D) {
                return p;
            } else {
                double lat2 = lat1 + distance * Math.cos(azimuth);
                double dPhi = Math.log(Math.tan(lat2 / 2.0D + 0.7853981633974483D) / Math.tan(lat1 / 2.0D + 0.7853981633974483D));
                double q = (lat2 - lat1) / dPhi;
                if (Double.isNaN(dPhi) || Double.isNaN(q) || Double.isInfinite(q)) {
                    q = Math.cos(lat1);
                }

                double dLon = distance * Math.sin(azimuth) / q;
                if (Math.abs(lat2) > 1.5707963267948966D) {
                    lat2 = lat2 > 0.0D ? 3.141592653589793D - lat2 : -3.141592653589793D - lat2;
                }

                double lon2 = (lon1 + dLon + 3.141592653589793D) % 6.283185307179586D - 3.141592653589793D;
                return !Double.isNaN(lat2) && !Double.isNaN(lon2) ? new LatLon(Angle.fromRadians(lat2).normalizedLatitude(), Angle.fromRadians(lon2).normalizedLongitude()) : p;
            }
        } else {
            throw new IllegalArgumentException("nullValue.AngleIsNull");
        }
    }

    public static LatLon rhumbEndPosition(LatLon p, double rhumbAzimuthRadians, double pathLengthRadians) {
        if (p == null) {
            throw new IllegalArgumentException("nullValue.LatLonIsNull");
        } else {
            return rhumbEndPosition(p, Angle.fromRadians(rhumbAzimuthRadians), Angle.fromRadians(pathLengthRadians));
        }
    }

    public static Angle getAverageDistance(Iterable<? extends LatLon> locations) {
        if (locations == null) {
            throw new IllegalArgumentException("nullValue.LocationsListIsNull");
        } else {
            double totalDistance = 0.0D;
            int count = 0;
            Iterator var5 = locations.iterator();

            while(var5.hasNext()) {
                LatLon p1 = (LatLon)var5.next();
                Iterator var7 = locations.iterator();

                while(var7.hasNext()) {
                    LatLon p2 = (LatLon)var7.next();
                    if (p1 != p2) {
                        double d = rhumbDistance(p1, p2).radians;
                        totalDistance += d;
                        ++count;
                    }
                }
            }

            return count == 0 ? Angle.ZERO : Angle.fromRadians(totalDistance / (double)count);
        }
    }

    public LatLon add(LatLon that) {
        if (that == null) {
            throw new IllegalArgumentException("nullValue.AngleIsNull");
        } else {
            Angle lat = Angle.normalizedLatitude(this.latitude.add(that.latitude));
            Angle lon = Angle.normalizedLongitude(this.longitude.add(that.longitude));
            return new LatLon(lat, lon);
        }
    }

    public LatLon subtract(LatLon that) {
        if (that == null) {
            throw new IllegalArgumentException("nullValue.AngleIsNull");
        } else {
            Angle lat = Angle.normalizedLatitude(this.latitude.subtract(that.latitude));
            Angle lon = Angle.normalizedLongitude(this.longitude.subtract(that.longitude));
            return new LatLon(lat, lon);
        }
    }

    public LatLon add(Position that) {
        if (that == null) {
            throw new IllegalArgumentException("nullValue.AngleIsNull");
        } else {
            Angle lat = Angle.normalizedLatitude(this.latitude.add(that.getLatitude()));
            Angle lon = Angle.normalizedLongitude(this.longitude.add(that.getLongitude()));
            return new LatLon(lat, lon);
        }
    }

    public LatLon subtract(Position that) {
        if (that == null) {
            throw new IllegalArgumentException("nullValue.AngleIsNull");
        } else {
            Angle lat = Angle.normalizedLatitude(this.latitude.subtract(that.getLatitude()));
            Angle lon = Angle.normalizedLongitude(this.longitude.subtract(that.getLongitude()));
            return new LatLon(lat, lon);
        }
    }

    public static boolean locationsCrossDateLine(Iterable<? extends LatLon> locations) {
        if (locations == null) {
            throw new IllegalArgumentException("nullValue.LocationsListIsNull");
        } else {
            LatLon pos = null;

            LatLon posNext;
            for(Iterator var3 = locations.iterator(); var3.hasNext(); pos = posNext) {
                posNext = (LatLon)var3.next();
                if (pos != null && Math.signum(pos.getLongitude().degrees) != Math.signum(posNext.getLongitude().degrees)) {
                    double delta = Math.abs(pos.getLongitude().degrees - posNext.getLongitude().degrees);
                    if (delta > 180.0D && delta < 360.0D) {
                        return true;
                    }
                }
            }

            return false;
        }
    }

    public static boolean locationsCrossDateline(LatLon p1, LatLon p2) {
        if (p1 != null && p2 != null) {
            if (Math.signum(p1.getLongitude().degrees) != Math.signum(p2.getLongitude().degrees)) {
                double delta = Math.abs(p1.getLongitude().degrees - p2.getLongitude().degrees);
                if (delta > 180.0D && delta < 360.0D) {
                    return true;
                }
            }

            return false;
        } else {
            throw new IllegalArgumentException("nullValue.LocationIsNull");
        }
    }

    public static List<LatLon> makeDatelineCrossingLocationsPositive(Iterable<? extends LatLon> locations) {
        if (locations == null) {
            throw new IllegalArgumentException("nullValue.LocationsListIsNull");
        } else {
            Iterator iter = locations.iterator();
            if (!iter.hasNext()) {
                return Collections.emptyList();
            } else {
                ArrayList<LatLon> newLocations = new ArrayList();
                Iterator var4 = locations.iterator();

                while(var4.hasNext()) {
                    LatLon location = (LatLon)var4.next();
                    if (location != null) {
                        if (location.getLongitude().degrees < 0.0D) {
                            newLocations.add(fromDegrees(location.getLatitude().degrees, location.getLongitude().degrees + 360.0D));
                        } else {
                            newLocations.add(location);
                        }
                    }
                }

                return newLocations;
            }
        }
    }

    public LatLon parseLatLon(String latLonString) {
        if (latLonString == null) {
            throw new IllegalArgumentException("nullValue.StringIsNull");
        } else {
            throw new UnsupportedOperationException();
        }
    }

    public String toString() {
        String las = String.format("Lat %7.4f°", this.getLatitude().getDegrees());
        String los = String.format("Lon %7.4f°", this.getLongitude().getDegrees());
        return "(" + las + ", " + los + ")";
    }

    public static boolean equals(LatLon a, LatLon b) {
        return a.getLatitude().equals(b.getLatitude()) && a.getLongitude().equals(b.getLongitude());
    }

    public int hashCode() {
        int result = this.latitude.hashCode();
        result = 29 * result + this.longitude.hashCode();
        return result;
    }

    public static Angle ellipsoidalForwardAzimuth(LatLon p1, LatLon p2, double equatorialRadius, double polarRadius) {
        if (p1 != null && p2 != null) {
            double f = (equatorialRadius - polarRadius) / equatorialRadius;
            double U1 = Math.atan((1.0D - f) * Math.tan(p1.latitude.radians));
            double cU1 = Math.cos(U1);
            double sU1 = Math.sin(U1);
            double U2 = Math.atan((1.0D - f) * Math.tan(p2.latitude.radians));
            double cU2 = Math.cos(U2);
            double sU2 = Math.sin(U2);
            double L = p2.longitude.subtract(p1.longitude).radians;
            double lambda = L;
            double sLambda = Math.sin(L);
            double cLambda = Math.cos(L);
            double lambda_prev = 1.7976931348623157E308D;

            for(int var30 = 0; Math.abs(lambda - lambda_prev) > 1.0E-12D && var30++ < 100; cLambda = Math.cos(lambda)) {
                lambda_prev = lambda;
                double sSigma = Math.sqrt(Math.pow(cU2 * sLambda, 2.0D) + Math.pow(cU1 * sU2 - sU1 * cU2 * cLambda, 2.0D));
                double cSigma = sU1 * sU2 + cU1 * cU2 * cLambda;
                double sigma = Math.atan2(sSigma, cSigma);
                double sAlpha = cU1 * cU2 * sLambda / sSigma;
                double cAlpha2 = 1.0D - sAlpha * sAlpha;
                double cSigmam2;
                if (Math.abs(cAlpha2) < 1.0E-6D) {
                    cSigmam2 = 0.0D;
                } else {
                    cSigmam2 = cSigma - 2.0D * sU1 * sU2 / cAlpha2;
                }

                double c = f / 16.0D * cAlpha2 * (4.0D + f * (4.0D - 3.0D * cAlpha2));
                lambda = L + (1.0D - c) * f * sAlpha * (sigma + c * sSigma * (cSigmam2 + c * cSigma * (-1.0D + 2.0D * cSigmam2)));
                sLambda = Math.sin(lambda);
            }

            return Angle.fromRadians(Math.atan2(cU2 * sLambda, cU1 * sU2 - sU1 * cU2 * cLambda));
        } else {
            throw new IllegalArgumentException("nullValue.PositionIsNull");
        }
    }

    public static double ellipsoidalDistance(LatLon p1, LatLon p2, double equatorialRadius, double polarRadius) {
        double F = (equatorialRadius - polarRadius) / equatorialRadius;
        double R = 1.0D - F;
        double EPS = 5.0E-14D;
        if (p1 != null && p2 != null) {
            double GLAT1 = p1.getLatitude().radians;
            double GLAT2 = p2.getLatitude().radians;
            double TU1 = R * Math.sin(GLAT1) / Math.cos(GLAT1);
            double TU2 = R * Math.sin(GLAT2) / Math.cos(GLAT2);
            double CU1 = 1.0D / Math.sqrt(TU1 * TU1 + 1.0D);
            double SU1 = CU1 * TU1;
            double CU2 = 1.0D / Math.sqrt(TU2 * TU2 + 1.0D);
            double S = CU1 * CU2;
            double BAZ = S * TU2;
            double FAZ = BAZ * TU1;
            double GLON1 = p1.getLongitude().radians;
            double GLON2 = p2.getLongitude().radians;
            double X = GLON2 - GLON1;

            double D;
            double SY;
            double CY;
            double Y;
            double C2A;
            double CZ;
            double E;
            double C;
            do {
                double SX = Math.sin(X);
                double CX = Math.cos(X);
                TU1 = CU2 * SX;
                TU2 = BAZ - SU1 * CU2 * CX;
                SY = Math.sqrt(TU1 * TU1 + TU2 * TU2);
                CY = S * CX + FAZ;
                Y = Math.atan2(SY, CY);
                double SA = S * SX / SY;
                C2A = -SA * SA + 1.0D;
                CZ = FAZ + FAZ;
                if (C2A > 0.0D) {
                    CZ = -CZ / C2A + CY;
                }

                E = CZ * CZ * 2.0D - 1.0D;
                C = ((-3.0D * C2A + 4.0D) * F + 4.0D) * C2A * F / 16.0D;
                D = X;
                X = ((E * CY * C + CZ) * SY * C + Y) * SA;
                X = (1.0D - C) * X * F + GLON2 - GLON1;
            } while(Math.abs(D - X) > 5.0E-14D);

            X = Math.sqrt((1.0D / R / R - 1.0D) * C2A + 1.0D) + 1.0D;
            X = (X - 2.0D) / X;
            C = 1.0D - X;
            C = (X * X / 4.0D + 1.0D) / C;
            D = (0.375D * X * X - 1.0D) * X;
            X = E * CY;
            S = 1.0D - E - E;
            S = ((((SY * SY * 4.0D - 3.0D) * S * CZ * D / 6.0D - X) * D / 4.0D + CZ) * SY * D + Y) * C * equatorialRadius * R;
            return S;
        } else {
            throw new IllegalArgumentException("nullValue.PositionIsNull");
        }
    }

    public static List<LatLon> computeShiftedLocations(Position oldLocation, Position newLocation, Iterable<? extends LatLon> locations) {
        if (oldLocation != null && newLocation != null) {
            if (locations == null) {
                throw new IllegalArgumentException("nullValue.PositionsListIsNull");
            } else {
                ArrayList<LatLon> newPositions = new ArrayList();
                Iterator var5 = locations.iterator();

                while(var5.hasNext()) {
                    LatLon location = (LatLon)var5.next();
                    Angle distance = greatCircleDistance(oldLocation, location);
                    Angle azimuth = greatCircleAzimuth(oldLocation, location);
                    newPositions.add(Position.greatCircleEndPosition(newLocation, azimuth, distance));
                }

                return newPositions;
            }
        } else {
            throw new IllegalArgumentException("nullValue.PositionIsNull");
        }
    }
}
