package com.tofly.ghrq_route.common.util.ArcgisUtils;

import android.content.Context;

import com.esri.arcgisruntime.ArcGISRuntimeEnvironment;
import com.esri.arcgisruntime.geometry.AngularUnit;
import com.esri.arcgisruntime.geometry.AngularUnitId;
import com.esri.arcgisruntime.geometry.GeodesicEllipseParameters;
import com.esri.arcgisruntime.geometry.GeodeticCurveType;
import com.esri.arcgisruntime.geometry.GeodeticDistanceResult;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.GeometryType;
import com.esri.arcgisruntime.geometry.LinearUnit;
import com.esri.arcgisruntime.geometry.LinearUnitId;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.PointCollection;
import com.esri.arcgisruntime.geometry.Polygon;
import com.esri.arcgisruntime.geometry.Polyline;
import com.esri.arcgisruntime.geometry.SpatialReference;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.layers.Layer;
import com.esri.arcgisruntime.mapping.ArcGISMap;
import com.esri.arcgisruntime.mapping.Basemap;
import com.esri.arcgisruntime.mapping.LayerList;
import com.esri.arcgisruntime.mapping.view.Callout;
import com.esri.arcgisruntime.mapping.view.Graphic;
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.tofly.ghrq_route.R;
import com.tofly.ghrq_route.module.gps.service.ArcgisLocationHelper;

/**
 * Created by Amu on 2017/6/5.
 */

public class ArcgisUtils {
    private Context mContext;
    private MapView mapView;
    private String mMapViewState;
    private ArcgisLocationHelper arcgisLocationHelper;

    /*德阳数据*/
    private static final int X_OFFSET_DY = 58672;
    private static final int Y_OFFSET_DY = 90;

    private static final String WGS84TOCHENGDUPRJ = "PROJCS[\"Xian_1980_3_Degree_GK_CM_105E\",GEOGCS[\"GCS_Xian_1980\",DATUM[\"D_Xian_1980\",SPHEROID[\"Xian_1980\",6378140.0,298.257]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",105.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",2380]]";
    private static final int WKID_WGS84 = 4326;

    public static final int render_padding = 50;
    public static final int render_padding_wide = 100;
    public static final int render_one_point_padding = 300;

    public ArcgisUtils(Context context){
        mContext = context;
        setLicense();
    }

    public static void setLicense() {
        ArcGISRuntimeEnvironment.setLicense("runtimelite,1000,rud7659408794,none,ZZ0RJAY3FY0GEBZNR002");
    }

    public void setMapView(MapView mapView) {
        this.mapView = mapView;
        this.mapView.setAttributionTextVisible(false);
        this.mapView.setBackgroundColor(mContext.getResources().getColor(R.color.white));
        setCalloutStyle();
    }

    private void setCalloutStyle() {
        Callout callout = mapView.getCallout();
        Callout.Style style = new Callout.Style(mContext);
        style.setBorderWidth(1);
        callout.setStyle(style);
    }

    public static SpatialReference getWgs84Spatial() {
        return SpatialReference.create(WKID_WGS84);
    }

    public static boolean isWgs84Point(Point point) {
        if (point != null && point.getSpatialReference() != null) {
            return  point.getSpatialReference().getWkid() == WKID_WGS84;
        }
        return false;
    }

    public static Point loctionProjectDefault(double longitude, double latitude){
        Point input = new Point(longitude, latitude, SpatialReference.create(WKID_WGS84));
/*        Point output = (Point) GeometryEngine.project(input, SpatialReference.create(WGS84TOCHENGDUPRJ));
        return new Point(output.getX() + X_OFFSET_DY, output.getY() + Y_OFFSET_DY);*/
        return input;
    }

    public static Point projectLocationDefault(double longitude, double latitude){
/*        Point geometry = new Point(longitude - X_OFFSET_DY, latitude - Y_OFFSET_DY, SpatialReference.create(WGS84TOCHENGDUPRJ));
        Point point = (Point) GeometryEngine.project(geometry, SpatialReference.create(WKID_WGS84));*/
        return new Point(longitude, latitude, SpatialReference.create(WKID_WGS84));
    }

    public static Point projectLocationDefault(Point input){
        Point geometry = new Point(input.getX() - X_OFFSET_DY, input.getY() - Y_OFFSET_DY, input.getSpatialReference());
        Point point = (Point) GeometryEngine.project(geometry, SpatialReference.create(WKID_WGS84));
        return point;
    }

    public static Polygon getLocationCircleGeometry(Point point, float radius, SpatialReference sp) {
        if (point == null || sp == null)
            return null;

        Polygon polygon = null;
        Point center = new Point(point.getX(), point.getY(), sp);
        GeodesicEllipseParameters parameters = new GeodesicEllipseParameters(center, radius, radius);
        parameters.setAngularUnit(new AngularUnit(AngularUnitId.DEGREES));
        parameters.setGeometryType(GeometryType.POLYGON);
        try {
            polygon = (Polygon) GeometryEngine.ellipseGeodesic(parameters);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
        return polygon;
    }

    public static double distance2Map(MapView mapView, android.graphics.Point screenPoint, int screenDistance){
        android.graphics.Point screenPoint2 = new android.graphics.Point(screenPoint.x + screenDistance, screenPoint.y);
        Point mapPoint1 = mapView.screenToLocation(screenPoint);
        Point mapPoint2 = mapView.screenToLocation(screenPoint2);
        double mapDistance = Math.sqrt(Math.pow(mapPoint1.getX() - mapPoint2.getX(), 2) + Math.pow(mapPoint1.getY() - mapPoint2.getY(), 2));
        return mapDistance;
    }

    public static double getTwoPointDistance(Point point0, Point point1) {
        double distance = 0;
        SpatialReference sp = point0.getSpatialReference();
        PointCollection collection = new PointCollection(sp);
        collection.add(point0);
        collection.add(point1);
        Polyline polyline = new Polyline(collection, sp);
        try {
            distance = GeometryEngine.length(polyline);
        }catch (NullPointerException e) {
            distance = 0;
        }
        return distance;
    }

    public static double getTwoPointDistance1(Point point0, Point point1) {
        double distance;
        try {
            GeodeticDistanceResult distanceResult = GeometryEngine.distanceGeodetic(point0, point1, new LinearUnit(LinearUnitId.METERS),
                    new AngularUnit(AngularUnitId.DEGREES), GeodeticCurveType.GEODESIC);
            distance = distanceResult.getDistance();
        }catch (NullPointerException e) {
            distance = 0;
        }
        return distance;
    }

    public static Point getMapCenter(MapView mapView) {
        float centreX = mapView.getX() + mapView.getWidth()  / 2;
        float centreY = mapView.getY() + mapView.getHeight() / 2;

        android.graphics.Point screenPoint = new android.graphics.Point(Math.round(centreX), Math.round(centreY));
        Point mapPoint = mapView.screenToLocation(screenPoint);
        return  mapPoint;
    }

    /**
     * 对坐标进行x,y偏移，偏移量以地图的屏幕坐标为基准
     * @param srcPoint 原始坐标(地图坐标)
     * @param xoff,yoff  相对于屏幕上上下，左右偏移量
     * @return 转换后的坐标(地图坐标)
     */
    public static Point pointAddOffset(MapView mapView, Point srcPoint, float xoff, float yoff) {
        Point dstPoint = srcPoint;
        if (srcPoint != null) {
            android.graphics.Point screenPoint = mapView.locationToScreen(srcPoint);
            screenPoint.x += xoff;
            screenPoint.y += yoff;
            dstPoint = mapView.screenToLocation(screenPoint);
        }
        return dstPoint;
    }

    /**
     * 判断是否为需要显示的图层
     *
     * @param layName
     * @return
     */
    public FeatureLayer getFeaureLayer(String layName) {
        FeatureLayer ftly = null;
        LayerList mapViewLayers = mapView.getMap().getOperationalLayers();
        //Layer[] mapViewLayers = mapView.getLayers();

        for (Layer layer : mapViewLayers) {
            if (layer instanceof FeatureLayer &&
                    layer.getName().equals(layName)) {//确认为管线图层，才返回设备字段
                ftly = (FeatureLayer) layer;
            }
        }
        return ftly;
    }

    public void hideArcgisMapCallout(){
        Callout callout = mapView.getCallout();
        if (callout != null && callout.isShowing()){
            callout.dismiss();
        }
    }

    public static boolean isGraphicOnLayerByLngLat(GraphicsOverlay layer, MapView mapView, Point srcPoint){
        android.graphics.Point screenPoint = mapView.locationToScreen(srcPoint);
        //Point screenPoint = mapView.toScreenPoint(srcPoint);
        return isGraphicOnLayerByXY(layer, mapView, screenPoint);
    }

    public static boolean isGraphicOnLayerByXY(GraphicsOverlay layer, MapView mapView, android.graphics.Point srcPoint){
        boolean isOnLayer = false;
        Graphic graphic = layer.getGraphics().get(0);
/*        int[] idsGraphic = layer.getGraphicIDs();
        if (idsGraphic != null && idsGraphic.length > 0){
            Graphic graphic = layer.getGraphic(idsGraphic[0]);*/
            if (graphic != null){
                double x = srcPoint.x;
                double y = srcPoint.y;

                Point geometry = (Point) graphic.getGeometry();
                android.graphics.Point point = mapView.locationToScreen(geometry);
                //geometry = mapView.toScreenPoint(geometry);
                double x1 = point.x;
                double y1 = point.y;

                if (Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1)) < 50) {
                    isOnLayer = true;
                }
            }
/*        }*/
        return  isOnLayer;
    }

    public void onPause(){
        if (mapView != null){
            //mMapViewState = mapView.retainState();
            mapView.pause();
        }
        stopArcgisLocation();
    }

    public void onResume(){
        if (mapView != null) {
            mapView.resume();
//            mapView.unpause();
//            if (mMapViewState != null) {
//                mapView.restoreState(mMapViewState);
//            }
        }
        if (arcgisLocationHelper != null) {
            arcgisLocationHelper.onResume();
        }
    }

    public void onStop() {
        if (arcgisLocationHelper != null) {
            arcgisLocationHelper.onStop();
        }
    }

    public void clearAllMpaData(){
        if (mapView != null){
            mapView.getGraphicsOverlays().clear();

            ArcGISMap arcGISMap = mapView.getMap();
            if (arcGISMap != null) {
                arcGISMap.getOperationalLayers().clear();
                Basemap basemap = arcGISMap.getBasemap();
                basemap.getBaseLayers().clear();
            }
        }
    }

    public void startArcgisLocation() {
        if (arcgisLocationHelper == null)
            arcgisLocationHelper = new ArcgisLocationHelper(mContext, mapView);
        arcgisLocationHelper.init();
    }

    public void stopArcgisLocation() {
        if (arcgisLocationHelper != null) {
            arcgisLocationHelper.onStop();
        }
    }

    public void resumeArcgisLocation() {
        if (arcgisLocationHelper != null) {
            arcgisLocationHelper.onResume();
        }
    }

    public void onDestroy(){
        clearAllMpaData();
        if (arcgisLocationHelper != null) {
            arcgisLocationHelper.onDestroy();
        }
        mapView = null;
    }
}
