package com.tofly.ghrq_route.module.map.controller;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import androidx.appcompat.app.AlertDialog;

import com.esri.arcgisruntime.ArcGISRuntimeEnvironment;
import com.esri.arcgisruntime.concurrent.Job;
import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.ArcGISFeature;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.FeatureTable;
import com.esri.arcgisruntime.data.Field;
import com.esri.arcgisruntime.data.Geodatabase;
import com.esri.arcgisruntime.data.GeodatabaseFeatureTable;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.data.ServiceFeatureTable;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
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.layers.ArcGISMapImageLayer;
import com.esri.arcgisruntime.layers.ArcGISSublayer;
import com.esri.arcgisruntime.layers.ArcGISTiledLayer;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.layers.Layer;
import com.esri.arcgisruntime.layers.SublayerList;
import com.esri.arcgisruntime.mapping.ArcGISMap;
import com.esri.arcgisruntime.mapping.Basemap;
import com.esri.arcgisruntime.mapping.GeoElement;
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.IdentifyLayerResult;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.symbology.PictureMarkerSymbol;
import com.esri.arcgisruntime.symbology.SimpleLineSymbol;
import com.esri.arcgisruntime.tasks.geoprocessing.GeoprocessingJob;
import com.esri.arcgisruntime.tasks.geoprocessing.GeoprocessingParameters;
import com.esri.arcgisruntime.tasks.geoprocessing.GeoprocessingResult;
import com.esri.arcgisruntime.tasks.geoprocessing.GeoprocessingString;
import com.esri.arcgisruntime.tasks.geoprocessing.GeoprocessingTask;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.mgq.base.utils.progressdialog.ProgressManager;
import com.mgq.base.utils.toast.ToastUtil;
import com.tofly.ghrq_route.R;
import com.tofly.ghrq_route.base.BaseApp;
import com.tofly.ghrq_route.base.ui.BaseMapController;
import com.tofly.ghrq_route.base.C;
import com.tofly.ghrq_route.base.MultiAsyncTask;
import com.tofly.ghrq_route.base.url.NetRequestURL;
import com.tofly.ghrq_route.base.URLResponseCode;
import com.tofly.ghrq_route.module.gps.domain.LocationGPSDataBean;
import com.tofly.ghrq_route.module.map.MapServiceTool;
import com.tofly.ghrq_route.module.map.domain.PipeQueryBean;
import com.tofly.ghrq_route.module.map.interfaces.MapLoadHelper;
import com.tofly.ghrq_route.module.map.service.Container;
import com.tofly.ghrq_route.module.map.service.MapPointAnalyzeHttpTask;
import com.tofly.ghrq_route.module.pipeAnalyze.domain.FieldsBean;
import com.tofly.ghrq_route.module.pipeAnalyze.domain.PipeAnalysisResultBean;
import com.tofly.ghrq_route.module.pipeAnalyze.domain.PipeAnalyzeMustShutFeatureBean;
import com.tofly.ghrq_route.module.pipeAnalyze.domain.PipeAnalyzeStatusBean;
import com.tofly.ghrq_route.module.sqlite.DBDaoHelper;
import com.tofly.ghrq_route.module.user.controller.UserController;
import com.tofly.ghrq_route.module.user.domain.MapUrlConfigDataBean;
import com.tofly.ghrq_route.module.user.domain.UserBean;
import com.tofly.ghrq_route.module.user.domain.UserOnlineMapDataBean;
import com.tofly.ghrq_route.module.user.domain.UserOnlineMapDataBean.MAP_CODE_KEY;
import com.tofly.ghrq_route.common.ui.adapter.PipenetCalloutViewAdapter;
import com.tofly.ghrq_route.common.ui.dialog.UiMainLayerManagerDailog;
import com.tofly.ghrq_route.common.ui.view.PipeAnalyzeResultBottomSheet;
import com.tofly.ghrq_route.common.util.ArcgisUtils.ArcgisUtils;
import com.tofly.ghrq_route.common.util.date.DateUtils;
import com.tofly.ghrq_route.common.util.net.http.HttpUtil;
import com.tofly.ghrq_route.common.util.sharedPreference.SharePreUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutionException;

/**
 * Created by lihualong on 2017/6/26.
 */

public class MapController {
    public static final int SLEEP_TIME = 500;

    private Context mContext;
    private BaseMapController baseMapController;
    private Container.ShowQueryRsultCallback queryRsultCallback;
    private Container.ShowOnlineQueryRsultCallback onlineQueryRsultCallback;
    private Container.ShowOnlineQueryWithKeyCallback onlineQueryWithKeyCallback;
    private ProgressDialog progressDialog;
    private String TAG = getClass().getName();
    private MapLoadHelper mapLoadHelper;
    private DBDaoHelper dbDaoHelper;
    private UserController userController;

    private static boolean mIsLoadTpk = false;
    private static boolean mIsLoadGeodata = false;
    private static boolean mIsLoadSatelite = false;

    private static Map<MapLoadHelper, List<ArcGISTiledLayer>> tpkOwnerMap = new HashMap<>();
    private static Map<MapLoadHelper, FeatureLayer[]> geoOwnerMap = new HashMap<>();
    private static Map<MapLoadHelper, List<ArcGISTiledLayer>> sateOwnerMap = new HashMap<>();

    public static List<ArcGISTiledLayer> tpkLayers;
    public static FeatureLayer[] geodatabaseLayers;
    public static List<ArcGISTiledLayer> satelliteLayers;
    public static GraphicsOverlay signPathLayer;
    public int signGraphicId = -1;

    public static final float MAP_OPACITY = 0.7f;

    private ArcGISTiledLayer onlineBaseMap;//在线地形图
    //private ArcGISTiledLayer onlineImageMap;//在线影像图
    private ArcGISMapImageLayer onlinePipeMap;//在线管线图
    private ArcGISTiledLayer onlinePoiMap;//在线地名图

    private ArrayList<FeatureLayer> featureLayers;
    private List<GraphicsOverlay> pipeQueryResultLayers = new ArrayList<>();

    private boolean mIsReturnAll = false;

    public MapController(Context context, BaseMapController baseMapController, MapLoadHelper mapLoadHelper) {
        this.mContext = context;
        this.baseMapController = baseMapController;
        this.mapLoadHelper = mapLoadHelper;
        dbDaoHelper = DBDaoHelper.getInstance();
    }

    public MapView getMapView() {
        return mapLoadHelper.getMapView();
    }
    public void onBaseMapLoaded() {
        mapLoadHelper.onBaseMapLoaded();
    }

    public void setQueryRsultCallback(Container.ShowQueryRsultCallback showQueryRsultCallback) {
        this.queryRsultCallback = showQueryRsultCallback;
    }

    public void setOnlineQueryRsultCallback(Container.ShowOnlineQueryRsultCallback queryRsultCallback) {
        this.onlineQueryRsultCallback = queryRsultCallback;
    }

    public void setOnlineQueryWithKeyCallback(Container.ShowOnlineQueryWithKeyCallback onlineQueryWithKeyCallback) {
        this.onlineQueryWithKeyCallback = onlineQueryWithKeyCallback;
    }

    public void closeMapQueryView(MapView mapView) {
        closeMapCallout(mapView);
        clearQueryResultLayers(mapView);
    }

    public void clearQueryResultLayers(MapView mapView) {
        if (pipeQueryResultLayers != null) {
            if (pipeQueryResultLayers.size() > 0) {
                for (GraphicsOverlay graphicsLayer : pipeQueryResultLayers) {
                    mapView.getGraphicsOverlays().remove(graphicsLayer);
                }
                pipeQueryResultLayers.clear();
            }
        }
    }

    private void closeMapCallout(MapView mapView){
        Callout callout = mapView.getCallout();
        if (callout != null && callout.isShowing()) {
            callout.dismiss();
        }
    }

    public boolean isLoadTpk() {
        return mIsLoadTpk;
    }

    public boolean isLoadGeodata() {
        return mIsLoadGeodata;
    }

    public boolean isLoadSatelite() {
        return mIsLoadSatelite;
    }

    public static void setTpkOwner(MapLoadHelper tpkOwner, List<ArcGISTiledLayer> tpkLayers) {
        tpkOwnerMap.put(tpkOwner, tpkLayers);
    }

    public static void setGeoOwner(MapLoadHelper geoOwner, FeatureLayer[] geoLayers) {
        geoOwnerMap.put(geoOwner, geoLayers);
    }

    public static void setSateOwner(MapLoadHelper sateOwner, List<ArcGISTiledLayer> sateLayers) {
        sateOwnerMap.put(sateOwner, sateLayers);
    }

    public void clearTpkOwner() {
        List<ArcGISTiledLayer> tpks = tpkOwnerMap.get(this.mapLoadHelper);
        if (tpks != null) {
            tpkOwnerMap.remove(this.mapLoadHelper);
            tpks.clear();
        }
    }

    public void clearGeoOwner() {
        FeatureLayer[] geos = geoOwnerMap.get(this.mapLoadHelper);
        if (geos != null) {
            geoOwnerMap.remove(this.mapLoadHelper);
            geos = null;
        }
    }

    public void clearSateOwner() {
        List<ArcGISTiledLayer> sates = sateOwnerMap.get(this.mapLoadHelper);
        if (sates != null) {
            sateOwnerMap.remove(this.mapLoadHelper);
            sates.clear();
        }
    }

    private static final int LOAD_TPK_LAYERS = 2;
    private static final int LOAD_GEODATABASE_LAYER = 3;
    private static final int LOAD_SATELLITE_LAYER = 4;
    private static final int SIGN_PATH = 5;
    private final int TO_SHOW_ONLINE_MAP = 6;

    private final int QUERY_ERROR = 1;
    private final int QUERY_OFFLINE_SUCCESS = 0;
    private final int QUERY_ONLINE_SUCCESS = -1;
    private final int QUERY_ONLINE_ERROR = -2;
    private final int QUERY_ONLINE_BY_KEY_SUCCESS = -3;
    private final int QUERY_ONLINE_BY_KEY_ERROR = -4;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int what = msg.what;
            Object obj = msg.obj;

            switch (what) {
                case QUERY_ERROR:
                    ProgressManager.getInstance().cancelProgress();
                    if (obj instanceof String) {
                        ToastUtil.showToast(mContext, (String) obj);
                    }
                    break;
                case QUERY_OFFLINE_SUCCESS:
                    if (obj instanceof List) {
                        List<PipeQueryBean> list = (List<PipeQueryBean>) obj;
                        showPipeQueryResult(list);
                    }
                    break;
                case QUERY_ONLINE_SUCCESS:
                    if (obj != null) {
                        Map<String, List<Feature>> layersMap = (Map<String, List<Feature>>) obj;
                        Bundle bundle = msg.getData();
                        String[] query_by_layer = null;
                        if (bundle != null){
                            int name_index = bundle.getInt(QUERY_PIPE_BY_NAME_KEY);
                            if (name_index == QUERY_PARAM_BY.QUERY_INDEX_LAYERNAME.getIndex()){
                                query_by_layer = bundle.getStringArray(QUERY_PIPE_BY_VALUE_KEY);
                            }
                        }
                        showOnlinePipeQueryResult(layersMap, query_by_layer);
                    }
                    break;
                case QUERY_ONLINE_ERROR:{
                    if (obj instanceof String) {
                        ToastUtil.showToast(mContext, (String) obj);
                    }
                    if (onlineQueryRsultCallback != null)
                        onlineQueryRsultCallback.showOnlineReuslt(false,null, null, null);
                }
                break;
                case QUERY_ONLINE_BY_KEY_SUCCESS:{
                    if (obj != null) {
                        String errStr = "查询成功";
                        showOnlinePipeQueryResult(true, errStr, obj);
                    }
                }
                break;
                case QUERY_ONLINE_BY_KEY_ERROR:{
                    showOnlinePipeQueryResult(false, (String) obj, null);
                }
                break;
                case LOAD_TPK_LAYERS:
                case LOAD_SATELLITE_LAYER:
                    ProgressManager.getInstance().cancelProgress();
                    if (obj instanceof List) {
                        if (mapLoadHelper != null) {
                            mapLoadHelper.loadtpkMap((List<ArcGISTiledLayer>) obj);
                        }
                    }
                    break;
                case LOAD_GEODATABASE_LAYER:
                    ProgressManager.getInstance().cancelProgress();
                    if (obj != null && obj instanceof FeatureLayer[]) {
                        if (mapLoadHelper != null) {
                            mapLoadHelper.loadGeodataMap((FeatureLayer[]) obj);
                        }
                    } else {
                        if (obj == null) {
                            if (mapLoadHelper != null) {
                                mapLoadHelper.turnToDownload();
                            }
                        }
                    }
                    break;
                case SIGN_PATH:
                    if (obj instanceof GraphicsOverlay) {
                        if (mapLoadHelper != null) {
                            mapLoadHelper.loadSignPathLayer((GraphicsOverlay) obj);
                        }
                    }
                    break;
                case TO_SHOW_ONLINE_MAP:
                    if (mapLoadHelper != null) {
                        mapLoadHelper.loadOnlineMap();
                    }
                    break;
            }
            if (progressDialog != null && progressDialog.isShowing()) {
                progressDialog.dismiss();
            }
        }
    };

    public void loadAllMap(MapView mapView) {
        boolean onlineMap = UiMainLayerManagerDailog.isOnlineMap();
        if (onlineMap) {
            loadOnlineMap(mapView);
        } else {
            loadOfflineMap(mapView);
        }
    }

    private void loadOfflineMap(MapView mapView) {
        if (UiMainLayerManagerDailog.isBaseMapLayerOn()) {
            loadBasemap(mapView);
        }else if (UiMainLayerManagerDailog.isSatelliteLayerOn()) {
            loadSatelliteLayer(mapView);
        }
        loadGeoDatabase();
    }

    // 影像图层
    public void loadSatelliteLayer(MapView mapView) {
        boolean isSatelliteOn = UiMainLayerManagerDailog.isSatelliteLayerOn();
        if (!isSatelliteOn)
            return;

        if (!mIsLoadSatelite){
            final UserBean userBean = BaseApp.getInstance().getLoginUser();
            if (userBean == null)
                return;

            mapView.setBackgroundColor(Color.WHITE);

            String strUploading = mContext.getResources().getString(R.string.loading_satellite);
            ProgressManager.getInstance().showProgress(mContext, null, strUploading, false);

            new Thread(() -> {
                MAP_CODE_KEY MAP_IMAGE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_OFFLINE_IMAGE.getCode());
                UserOnlineMapDataBean userMapData = dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_IMAGE.getCode());
                List<String> satellties = new ArrayList<>();
                if (userMapData != null) {
                    satellties.add(userMapData.getCval());
                }
                if (satellties.size() > 0) {
                    List<ArcGISTiledLayer> localSatelliteLayers = new ArrayList<>();
                    for (String fileName : satellties) {
                        String filePath = C.dir.data + fileName;
                        if (new File(filePath).exists()) {
                            ArcGISTiledLayer localTetalliteLayer = new ArcGISTiledLayer(filePath);
                            localTetalliteLayer.setOpacity(MAP_OPACITY);
                            localSatelliteLayers.add(localTetalliteLayer);
                        }
                    }
                    if (localSatelliteLayers.size() > 0) {
                        //sendResult(baseMapController.getString(R.string.have_no_satellie), QUERY_ERROR);
                        mIsLoadSatelite = true;
                    }
                    satelliteLayers = localSatelliteLayers;

                    sendResult(localSatelliteLayers, LOAD_SATELLITE_LAYER);
                } else {
                    sendResult(mContext.getString(R.string.have_no_satellie), QUERY_ERROR);
                    Log.w(TAG, "run: 没有可显示的影像图");
                }
            }).start();
        }else {
            loadSatellitesByOwner();
        }
    }

    public void loadSatellitesByOwner(){
        if (mapLoadHelper != null && satelliteLayers != null){
            List<ArcGISTiledLayer> sates = sateOwnerMap.get(mapLoadHelper);
            if (sates != null) {
                mapLoadHelper.loadtpkMap(sates);
            }else {
                sates = new ArrayList();
                for (ArcGISTiledLayer tiledLayer : satelliteLayers) {
                    sates.add(tiledLayer.copy());
                }
                setSateOwner(mapLoadHelper, sates);
                mapLoadHelper.loadtpkMap(sates);
            }
        }
    }

    // 管网图层
    public void loadGeoDatabase() {
        boolean isPipeOn = UiMainLayerManagerDailog.isPipeLayerOn();
        if (!isPipeOn)
            return;

        if (!mIsLoadGeodata){
            final UserBean userBean = BaseApp.getInstance().getLoginUser();
            if (userBean == null)
                return;

            String strUploading = mContext.getResources().getString(R.string.loading_geodata);
            ProgressManager.getInstance().showProgress(mContext, null, strUploading, false);

            Thread thread = new Thread(() -> {
                MAP_CODE_KEY MAP_PIPE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_OFFLINE_PIPE.getCode());
                UserOnlineMapDataBean userMapData = dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_PIPE.getCode());
                List<String> geodatabases = new ArrayList<>();
                if (userMapData != null) {
                    geodatabases.add(userMapData.getCval());
                }
                if (C.bUseLocalMap) {
                    geodatabases.add(C.locak_geo_file);
                }

                if (geodatabases.size() > 0) {
                    List<FeatureLayer> featureLayerList = new ArrayList<>();
                    MultiAsyncTask geoMultiTask = new MultiAsyncTask(MultiAsyncTask.InvokeMode.ASYNC, new MultiAsyncTask.OnTasksFinishListener() {
                        @Override
                        public void onFinish() {
                            FeatureLayer[] featureLayerArr = null;
                            int size = featureLayerList .size();
                            if (size > 0) {
                                featureLayerArr = new FeatureLayer[size];
                                for (int i = 0; i < featureLayerList.size() ; i++) {
                                    featureLayerArr[i] = featureLayerList.get(featureLayerList.size()-1 - i);
                                }
                                mIsLoadGeodata = true;
                            }else {
                                sendResult(mContext.getString(R.string.have_no_geodata), QUERY_ERROR);
                            }
                            geodatabaseLayers = featureLayerArr;
                            sendResult(featureLayerArr, LOAD_GEODATABASE_LAYER);
                        }

                        @Override
                        public void onTimeOut() {
                            sendResult(mContext.getString(R.string.have_no_geodata), QUERY_ERROR);
                        }
                    });
                    boolean hasTask = false;
                    for (String geoFileName : geodatabases) {
                        String filePath = C.dir.data + geoFileName;
                        if (new File(filePath).exists()) {
                            final Geodatabase geodatabase = new Geodatabase(filePath);
                            if (geodatabase != null) {
                                hasTask = true;
                                GeoTask geoTask = new GeoTask(geodatabase, featureLayerList);
                                geoMultiTask.addTask(geoTask);
                            }
                        }
                    }
                    if (hasTask)
                        geoMultiTask.execute();
                    else {
                        sendResult(mContext.getString(R.string.have_no_geodata), QUERY_ERROR);
                    }
                } else {
                    sendResult(mContext.getString(R.string.have_no_geodata), QUERY_ERROR);
                    Log.w(TAG, "run: 没有可显示管网地图");
                }
            });
            thread.start();
        }else {
            loadGeoByOwner();
        }
    }

    public void loadGeoByOwner() {
        if (mapLoadHelper != null && geodatabaseLayers != null){
            FeatureLayer[] geos = geoOwnerMap.get(mapLoadHelper);
            if (geos != null) {
                mapLoadHelper.loadGeodataMap(geos);
            }else {
                geos = geodatabaseLayers.clone();
                setGeoOwner(mapLoadHelper, geos);
                mapLoadHelper.loadGeodataMap(geos);
            }
        }
    }

    class GeoTask extends MultiAsyncTask.AsyncTask {
        Geodatabase geodatabase;
        List<FeatureLayer> featureLayers;
        public GeoTask(Geodatabase geodatabase, List<FeatureLayer> featureLayers) {
            this.geodatabase = geodatabase;
            this.featureLayers = featureLayers;
        }
        @Override
        public void taskRun() {
            geodatabase.loadAsync();
            geodatabase.addDoneLoadingListener(() -> {
                List<GeodatabaseFeatureTable> tables = geodatabase.getGeodatabaseFeatureTables();
                List<FeatureLayer> layerList = new ArrayList<>();
                for (GeodatabaseFeatureTable featureTable : tables) {
                    FeatureLayer fl = new FeatureLayer(featureTable);
                    fl.setLabelsEnabled(true);
                    layerList.add(fl);
                }
                featureLayers.addAll(layerList);
                finishTask();
            });
        }
    }

    // 地形图
    public void loadBasemap(MapView mapView) {
        boolean isTpkOn = UiMainLayerManagerDailog.isBaseMapLayerOn();
        if (!isTpkOn)
            return;

        if (!mIsLoadTpk){
            final UserBean userBean = BaseApp.getInstance().getLoginUser();
            if (userBean == null)
                return;

            mapView.setBackgroundColor(Color.WHITE);

            String strUploading = mContext.getResources().getString(R.string.loading_map);
            ProgressManager.getInstance().showProgress(mContext, null, strUploading, false);

            new Thread(() -> {
                MAP_CODE_KEY MAP_TPK = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_OFFLINE_TPK.getCode());
                UserOnlineMapDataBean userMapData = dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_TPK.getCode());
                if (userMapData != null || C.bUseLocalMap) {
                    List<String> tpkNames = new ArrayList<>();
                    tpkNames.add(userMapData.getCval());
                    if (C.bUseLocalMap) {
                        tpkNames.add(C.local_tpk_file);
                    }
                    List<ArcGISTiledLayer> arcGISLocalTiledLayerList = new ArrayList<>();
                    for (String tpkName : tpkNames) {
                        String filePath = C.dir.data + tpkName;
                        Log.w(TAG, "run: tpkName = " + tpkName);
                        if (new File(filePath).exists()) {
                            ArcGISTiledLayer arcGISLocalTiledLayer = new ArcGISTiledLayer(filePath);
                            arcGISLocalTiledLayer.setOpacity(MAP_OPACITY);
                            arcGISLocalTiledLayerList.add(arcGISLocalTiledLayer);
                        }
                    }
                    if (arcGISLocalTiledLayerList.isEmpty()) {
                        sendResult(mContext.getString(R.string.have_no_tpk), QUERY_ERROR);
                    }else {
                        mIsLoadTpk = true;
                    }
                    tpkLayers = arcGISLocalTiledLayerList;

                    sendResult(arcGISLocalTiledLayerList, LOAD_TPK_LAYERS);
                } else {
                    sendResult(mContext.getString(R.string.have_no_tpk), QUERY_ERROR);
                    Log.w(TAG, "run: 没有可显示的基础图");
                }
            }).start();
        }else {
            loadTpkByOwner();
        }
    }

    public void loadTpkByOwner() {
        if (mapLoadHelper != null && tpkLayers != null) {
            List<ArcGISTiledLayer> tpks = tpkOwnerMap.get(mapLoadHelper);
            if (tpks != null) {
                mapLoadHelper.loadtpkMap(tpks);
            }else {
                tpks = new ArrayList();
                for (ArcGISTiledLayer tiledLayer : tpkLayers) {
                    tpks.add(tiledLayer.copy());
                }
                setTpkOwner(mapLoadHelper, tpks);
                mapLoadHelper.loadtpkMap(tpks);
            }
        }
    }

    public void loadOnlineMap(MapView mapView) {
        if (mapView == null)
            return;

        final UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (userBean == null)
            return;

        mapView.setBackgroundColor(Color.WHITE);

        new Thread(() -> {

            ArcGISRuntimeEnvironment.setLicense("runtimelite,1000,rud7659408794,none,ZZ0RJAY3FY0GEBZNR002");

            baseMapController.clearMapData();

            ArcGISMap arcMap = baseMapController.getArcMap();
            if (arcMap == null)
                arcMap = new ArcGISMap();

            Basemap basemap = arcMap.getBasemap();
            LayerList layerList = basemap.getBaseLayers();

            String url = NetRequestURL.ONLINE_TPK_INTERNAL;
            ArcGISTiledLayer onlineMap;

            /*底图图层*/
            MAP_CODE_KEY MAP_BASE = null;
            int index = -1;
            if (UiMainLayerManagerDailog.isBaseMapLayerOn()) {
                url = NetRequestURL.ONLINE_TPK_INTERNAL;
                MAP_BASE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_TPK1.getCode());
            }else if (UiMainLayerManagerDailog.isSatelliteLayerOn()){
                url = NetRequestURL.ONLINE_IMAGE_INTERNAL;
                MAP_BASE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_IMAGE.getCode());
            }
            if (MAP_BASE != null) {
                UserOnlineMapDataBean baseDataBean =
                        dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_BASE.getCode());
                if (baseDataBean != null) {
                    String base_url = baseDataBean.getCval();
                    if (base_url != null && !base_url.isEmpty()){
                        url = NetRequestURL.getReplaceUrl(base_url);
                    }
                }

                onlineMap = new ArcGISTiledLayer(url);
                onlineMap.setOpacity(MAP_OPACITY);
                onlineBaseMap = onlineMap;
                layerList.add(++index, onlineMap);
            }

            /*地名图层*/
            boolean isPoiOn = UiMainLayerManagerDailog.isPoiLayerOn();
            if (isPoiOn) {
                url = NetRequestURL.ONLINE_POI_INTERNAL;
                MAP_CODE_KEY MAP_POI = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_POI.getCode());
                UserOnlineMapDataBean poiDataBean =
                        dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_POI.getCode());
                if (poiDataBean != null) {
                    String poi_url = poiDataBean.getCval();
                    if (poi_url != null && !poi_url.isEmpty()){
                        url = NetRequestURL.getReplaceUrl(poi_url);
                    }
                }
                onlineMap = new ArcGISTiledLayer(url);
                onlineMap.setOpacity(MAP_OPACITY);
                onlinePoiMap = onlineMap;
                layerList.add(++index, onlineMap);
            }

            /*管线图层*/
            boolean isPipeOn = UiMainLayerManagerDailog.isPipeLayerOn();
            if (isPipeOn) {
                url = NetRequestURL.ONLINE_PIPE_INTERNAL;
                MAP_CODE_KEY MAP_PIPE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_PIPE.getCode());
                UserOnlineMapDataBean pipeDataBean =
                        dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_PIPE.getCode());
                if (pipeDataBean != null) {
                    String pipe_url = pipeDataBean.getCval();
                    if (pipe_url != null && !pipe_url.isEmpty()){
                        url = NetRequestURL.getReplaceUrl(pipe_url);
                    }
                }
                ArcGISMapImageLayer pipeOnlineMap = new ArcGISMapImageLayer(url);
                pipeOnlineMap.setOpacity(MAP_OPACITY);
                onlinePipeMap = pipeOnlineMap;
                layerList.add(++index, pipeOnlineMap);
            }

            mapView.setMap(arcMap);
            baseMapController.setArcMap(arcMap);
            arcMap.addDoneLoadingListener(() -> {
                sendResult(onlinePipeMap, TO_SHOW_ONLINE_MAP);
                baseMapController.onlineMapLoaded();
            });
            arcMap.loadAsync();
        }).start();
    }

    public void showCallOutAtMap(MapView mapView, Feature feature) {
        List<FeatureLayer> felList = getAllFeatureLayer(mapView);
        if (felList != null && !felList.isEmpty()) {
            for (FeatureLayer fel : felList) {
                fel.clearSelection();
                try {
                    FeatureTable table = fel.getFeatureTable();
                    List<Field> fields = table.getFields();
                    View calloutView = getPipenetCalloutViewFromFeature(mapView, feature, fields, table.getTableName());
                    Point centerPoint = null;
                    Geometry geometry = feature.getGeometry();
                    if (geometry instanceof Polyline) {
                        Polyline polyline = (Polyline) feature.getGeometry();
                        Iterable<Point> points = polyline.getParts().getPartsAsPoints();
                        int pointCount = polyline.getParts().size();
                        for (int index = 0; index < pointCount; index ++) {
                            Point point = points.iterator().next();
                            if (index == pointCount / 2) {
                                centerPoint = point;
                                break;
                            }
                        }
                    } else if (geometry instanceof Point) {
                        centerPoint = (Point) geometry;
                    }
                    fel.selectFeature(feature);
                    Callout callout = mapView.getCallout();
                    if (callout != null)
                        callout.show(calloutView, centerPoint);//显示弹出框
                    zoomToScale(mapView, centerPoint, 2000);
                } catch (Exception e) {
                    e.printStackTrace();
                    ToastUtil.showToast(mContext, e.getMessage());
                }
            }
        }
    }

    public void showResult(MapView mapView, Feature ff, List<Field> fields, android.graphics.Point screenPoint, String tableName) {
        View view = getPipenetCalloutViewFromFeature(mapView, ff, fields, tableName);
        Geometry geometry = ff.getGeometry();
        Point toPoint;
        if (geometry instanceof Polyline) {
            toPoint = mapView.screenToLocation(screenPoint);
        } else {
            toPoint = (Point) geometry;
        }
        Callout callout = mapView.getCallout();
        if (callout != null)
            callout.show(view, toPoint);//显示弹出框
    }

    public void showCalloutFromJsonObject(MapView mapView, JsonObject jsonAttributes, JsonObject jsonGeometry, String tableName) {
        View view = getPipenetCalloutViewFromJsonObject(mapView, jsonAttributes, jsonGeometry, tableName);
        if (view != null && jsonGeometry != null) {
            Geometry geometry = Geometry.fromJson(jsonGeometry.toString());
            Point centerPoint = geometry.getExtent().getCenter();
            if (centerPoint != null) {
                baseMapController.gotoSearchCoordinate(mapView, centerPoint.getX(), centerPoint.getY(), null);
                int offset = BaseApp.dip2px(125);
                Point dstPoint =  ArcgisUtils.pointAddOffset(mapView, centerPoint, 0, -offset);
                if (dstPoint != null) {
                    mapView.setViewpointCenterAsync(dstPoint);
                }

                Callout callout = mapView.getCallout();
                if (callout != null)
                    callout.show(view, centerPoint);//显示弹出框
            }
        }
    }
    //属性查询需要显示的view（不使用配置文件排序）
    public View getPipenetCalloutViewFromJsonObject(final MapView mapView, JsonObject jsonAttributes, JsonObject jsonGeometry, String tableName) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View rootView = inflater.inflate(R.layout.pipe_query_callout, null);//管线详情布局
        ListView listView = rootView.findViewById(R.id.feature_attrs_listview);
        ImageView btnClose = rootView.findViewById(R.id.image_callout_close);
        Map<String, Object> attrsMap = new HashMap<>();
        for (Map.Entry<String, JsonElement> entry : jsonAttributes.entrySet()) {
            String key = entry.getKey();
            JsonElement value = entry.getValue();
            String strValue = "";
            if (value != null) {
               strValue = value.toString().replaceAll("\\\"","");
            }
            attrsMap.put(key, strValue);
        }

        List<FieldsBean> fields = dbDaoHelper.getMapFieldConfigList(tableName);
        boolean hasConfig = fields != null && fields.size() > 0;
        PipenetCalloutViewAdapter adapter;
        if (hasConfig){
            adapter = new PipenetCalloutViewAdapter(mContext, attrsMap, fields, tableName, true, true);
        }else {
            adapter = new PipenetCalloutViewAdapter(mContext, attrsMap, null,  tableName, true, true);
        }
        listView.setAdapter(adapter);

        btnClose.setOnClickListener(v -> {
            closeMapQueryView(mapView);
            baseMapController.clearMarkGraphic(mapView);
        });
        return rootView;
    }

    //属性查询需要显示的view（不使用配置文件排序）
    public View getPipenetCalloutViewFromFeature(final MapView mapView, Feature feature, List<Field> fieldList, String tableName) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View rootView = inflater.inflate(R.layout.pipe_query_callout, null);//管线详情布局
        ListView listView = rootView.findViewById(R.id.feature_attrs_listview);
        ImageView btnClose = rootView.findViewById(R.id.image_callout_close);
        TextView textNav = rootView.findViewById(R.id.text_nav);
        Map<String, Object> attrsMap = feature.getAttributes();
        List<FieldsBean> fields = dbDaoHelper.getMapFieldConfigList(tableName);
        boolean hasConfig = fields != null && fields.size() > 0;
        PipenetCalloutViewAdapter adapter;
        if (hasConfig){
            adapter = new PipenetCalloutViewAdapter(mContext, attrsMap, fields, tableName, false, true);
        }else {
            adapter = new PipenetCalloutViewAdapter(mContext, attrsMap, fieldList, tableName, false, true);
        }
        listView.setAdapter(adapter);

        textNav.setOnClickListener(view -> {
            Geometry geometry = feature.getGeometry();
            Point center = geometry.getExtent().getCenter();
            Point location = baseMapController.getLocation();
            baseMapController.onRouteBtnPressed(location, center);
        });

        btnClose.setOnClickListener(v -> {
            closeMapQueryView(mapView);
            if (feature != null && feature.getFeatureTable() != null) {
                Layer layer = feature.getFeatureTable().getLayer();
                if (layer != null) {
                    if (layer instanceof FeatureLayer) {
                        ((FeatureLayer) layer).clearSelection();
                    }
                }
            }
        });
        return rootView;
    }

    //
    private void showPipeQueryResult(final List<PipeQueryBean> pipeQueryBeens) {
        if (mIsReturnAll) {
            queryRsultCallback.showResult(null, null, null, null, pipeQueryBeens);
        }else {
            if (pipeQueryBeens.size() > 0) {
                final String[] tableNames = new String[pipeQueryBeens.size()];
                for (int i = 0; i < pipeQueryBeens.size(); i++) {
                    tableNames[i] = pipeQueryBeens.get(i).tableName;
                }
                AlertDialog alertDialog = new AlertDialog.Builder(mContext)
                        .setTitle("请选择需要显示的图层！")
                        .setCancelable(true)
                        .setSingleChoiceItems(tableNames, -1, (dialog, which) -> {
                            dialog.dismiss();
                            // 显示第一条
                            PipeQueryBean pipeQueryBean = pipeQueryBeens.get(which);
                            List<Feature> whichLayerList = pipeQueryBean.whichLayerList;
                            Feature ff = whichLayerList.get(0);
                            String tableName = pipeQueryBean.tableName;
                            FeatureLayer fel = pipeQueryBean.featureLayer;
                            FeatureTable table = fel.getFeatureTable();
                            List<Field> fields = table.getFields();
                            queryRsultCallback.showResult(ff, fields, whichLayerList, tableName, pipeQueryBeens);
                        })
                        .setCancelable(true)
                        .create();
                alertDialog.setCanceledOnTouchOutside(false);
                alertDialog.show();
            }
        }
    }

    /**
     * 离线管线查询
     */
    private void queryPipe(final android.graphics.Point screenPoint, MapView mapView) {
        closeMapQueryView(mapView);

        if (progressDialog == null) {
            progressDialog = new ProgressDialog(mContext);
            progressDialog.setMessage("管网数据查询中...");
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }

        new Thread(() -> {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ListenableFuture<List<IdentifyLayerResult>> identifyFuture =
                    mapView.identifyLayersAsync(screenPoint, 10, false, 10);
            identifyFuture.addDoneListener(() -> {
                try {
                    List<PipeQueryBean> shotFeatureList = new ArrayList<>();
                    List<IdentifyLayerResult> results = identifyFuture.get();
                    for (IdentifyLayerResult result : results) {
                        PipeQueryBean pipeQueryBean = new PipeQueryBean();
                        List<Feature> layerList = new ArrayList<>();
                        FeatureLayer feaLayer = null;
                        if (result.getLayerContent() instanceof FeatureLayer) {
                            feaLayer = (FeatureLayer) result.getLayerContent();
                            feaLayer.clearSelection();
                        }
                        for (Object element : result.getElements()) {
                            if (element instanceof Feature) {
                                Feature feature = (Feature) element;
                                layerList.add(feature);
                                if (feaLayer != null) {
                                    feaLayer.selectFeature(feature);
                                }
                            }
                        }
                        if (layerList.size() > 0) {
                            pipeQueryBean.whichLayerList = layerList;
                            pipeQueryBean.tableName = result.getLayerContent().getName();
                            pipeQueryBean.featureLayer = feaLayer;
                            shotFeatureList.add(pipeQueryBean);
                        }
                    }
                    if (shotFeatureList.size() > 0) {
                        sendResult(shotFeatureList, QUERY_OFFLINE_SUCCESS);
                    } else {
                        sendResult("未点击到管线", QUERY_ERROR);
                    }
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                    sendResult("未点击到管线", QUERY_ERROR);
                }
            });
        }).start();
    }

    /** 在线管网查询 **/
    public void showOnlineResult(MapView mapView, Feature result0, String tabbleName) {
        View view = getPipenetCalloutViewFromFeature(mapView, result0, null, tabbleName);

        Geometry geometry = result0.getGeometry();
        Point toPoint;
        if (geometry instanceof Polyline) {
            Polyline polyline = (Polyline) geometry;
            int lineColor = mContext.getResources().getColor(R.color.top_bar_light);
            SimpleLineSymbol lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, lineColor, 5.0f);
            GraphicsOverlay graphicsLayer = new GraphicsOverlay();
            graphicsLayer.getGraphics().add(new Graphic(polyline, lineSymbol));
            mapView.getGraphicsOverlays().add(graphicsLayer);
            pipeQueryResultLayers.add(graphicsLayer);
            Iterable<Point> points = polyline.getParts().getPartsAsPoints();
            int pointCount = polyline.getParts().size();
            double x = 0; double y = 0;
            for (int i = 0; i < pointCount; i++) {
                Point point = points.iterator().next();
                x += point.getX();
                y += point.getY();
            }
            toPoint = new Point(x / pointCount, y / pointCount, polyline.getSpatialReference());
        } else {
            toPoint = (Point) geometry;
            BitmapDrawable signedLoc = (BitmapDrawable) mContext.getResources().getDrawable(R.mipmap.danger_location);
            PictureMarkerSymbol symbol = new PictureMarkerSymbol(signedLoc);
            GraphicsOverlay graphicsLayer = new GraphicsOverlay();
            graphicsLayer.getGraphics().add(new Graphic(geometry, symbol));
            mapView.getGraphicsOverlays().add(graphicsLayer);
            pipeQueryResultLayers.add(graphicsLayer);
        }
        Callout callout = mapView.getCallout();
        if (callout != null)
            callout.show(view, toPoint);//显示弹出框
    }

    private void showOnlinePipeQueryResult(final Map<String, List<Feature>> layersMap, String[] query_by_layer){
        if (mContext != null) {
            Activity activity = (Activity) mContext;
            if (activity.isFinishing() || activity.isDestroyed()) {
                return;
            }
        }

        if (layersMap != null && layersMap.size() > 0) {
            Set<String> keySets = layersMap.keySet();
            final String[] tableNames = keySets.toArray(new String[keySets.size()]);
            if (layersMap.size() == 1){
                String tableName = tableNames[0];
                List<Feature> results = layersMap.get(tableName);
                Feature result0 = results.get(0);
                boolean isSuccess = true;
                if (query_by_layer != null){
                    List<String> layerNames = Arrays.asList(query_by_layer);
                    if (!layerNames.contains(tableName)){
                        isSuccess = false;
                        result0 = null;
                    }
                    if (onlineQueryRsultCallback != null)
                        onlineQueryRsultCallback.showOnlineReuslt(isSuccess, result0, results, tableName);
                }else {
                    queryRsultCallback.showOnlineResult(result0, results, tableName, layersMap);
                }
            }else {
                if (query_by_layer != null){
                    List<String> layerNames = Arrays.asList(query_by_layer);
                    boolean hasTable = false;
                    List<Feature> results = null;
                    Feature result0 = null;
                    String findTableName = null;
                    for (Map.Entry<String, List<Feature>> entry : layersMap.entrySet()) {
                        String tableName = entry.getKey();
                        if (layerNames.contains(tableName)) {
                            hasTable = true;
                            results = entry.getValue();
                            result0 = results.get(0);
                            findTableName = tableName;
                            break;
                        }
                    }
                    if (hasTable){
                        if (onlineQueryRsultCallback != null)
                            onlineQueryRsultCallback.showOnlineReuslt(true, result0, results, findTableName);
                    }else {
                        if (onlineQueryRsultCallback != null)
                            onlineQueryRsultCallback.showOnlineReuslt(false, null, null, null);
                    }
                }else {
                    if (mIsReturnAll) {
                        queryRsultCallback.showOnlineResult(null, null, null, layersMap);
                    }else  {
                        AlertDialog alertDialog = new AlertDialog.Builder(mContext)
                                .setTitle("请选择需要显示的图层！")
                                .setCancelable(true)
                                .setSingleChoiceItems(tableNames, -1, (dialog, which) -> {
                                    dialog.dismiss();
                                    //显示第一条
                                    String tableName = tableNames[which];
                                    List<Feature> results = layersMap.get(tableName);
                                    Feature result0 = null;
                                    if (results != null) {
                                        result0 = results.get(0);
                                    }
                                    queryRsultCallback.showOnlineResult(result0, results, tableName, layersMap);
                                })
                                .setCancelable(true)
                                .create();
                        alertDialog.setCanceledOnTouchOutside(false);
                        alertDialog.show();
                    }
                }
            }
        }
    }

    /*根据点击的点查询设备*/
    private void query_pipe_online_by_tap(final android.graphics.Point screenPoint, MapView mapView){
        closeMapQueryView(mapView);

        if (progressDialog == null) {
            progressDialog = new ProgressDialog(mContext);
            progressDialog.setMessage("管网数据查询中...");
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }

        new Thread(() -> {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            ListenableFuture<List<IdentifyLayerResult>> identifyFuture =
                    mapView.identifyLayersAsync(screenPoint, 10, false, 10);
            identifyFuture.addDoneListener(() -> {
                try {
                    Map<String, List<Feature>> layerMap = new HashMap<>();
                    List<IdentifyLayerResult> layerResults = identifyFuture.get();
                    for (IdentifyLayerResult result : layerResults) {
                        List<IdentifyLayerResult> sublayerResults = result.getSublayerResults();
                        for (IdentifyLayerResult sublayerResult : sublayerResults) {
                            List<GeoElement> elements = sublayerResult.getElements();
                            for (GeoElement identifiedElement : elements) {
                                if (identifiedElement instanceof Feature) {
                                    ArcGISFeature feature = (ArcGISFeature) identifiedElement;
                                    String layerName = feature.getFeatureTable().getTableName();
                                    if (!layerMap.containsKey(layerName)) {
                                        List<Feature> results = new ArrayList<>();
                                        results.add(feature);
                                        layerMap.put(layerName, results);
                                    }else {
                                        List<Feature> results = layerMap.get(layerName);
                                        if (results == null)
                                            results = new ArrayList<>();
                                        results.add(feature);
                                    }
                                }
                            }
                        }
                    }
                    if (layerMap.size() > 0) {
                        sendResult(layerMap, QUERY_ONLINE_SUCCESS);
                    } else {
                        sendResult("未点击到管线", QUERY_ERROR);
                    }
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                    sendResult("未点击到管线", QUERY_ERROR);
                }
            });
        }).start();
    }

    private void query_pipe_online(final android.graphics.Point screenPoint, MapView mapView,
                                   final QUERY_PARAM_BY param_by, final String[] param_value){
        closeMapQueryView(mapView);

        if (progressDialog == null) {
            progressDialog = new ProgressDialog(mContext);
            progressDialog.setMessage("管网数据查询中...");
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }

        new Thread(() -> {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (onlinePipeMap == null) {
                String pipe_url = NetRequestURL.ONLINE_PIPE_INTERNAL;
                UserBean userBean = BaseApp.getInstance().getLoginUser();
                MAP_CODE_KEY MAP_PIPE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_PIPE.getCode());
                UserOnlineMapDataBean pipeDataBean =
                        dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_PIPE.getCode());
                if (pipeDataBean != null) {
                    String cval = pipeDataBean.getCval();
                    if (cval != null && !cval.isEmpty()){
                        pipe_url = NetRequestURL.getReplaceUrl(cval);
                    }
                }
                onlinePipeMap = new ArcGISMapImageLayer(pipe_url);
            }

            final ListenableFuture<IdentifyLayerResult> identifyFuture = mapView.identifyLayerAsync(
                    onlinePipeMap, screenPoint, 15, false, 10);
            identifyFuture.addDoneListener(() -> {
                try {
                    Map<String, List<Feature>> layerMap = new HashMap<>();
                    // get the identify results from the future - returns when the operation is complete
                    IdentifyLayerResult identifyLayerResult = identifyFuture.get();
                    List<IdentifyLayerResult> layerResults = identifyLayerResult.getSublayerResults();
                    for (IdentifyLayerResult layerResult : layerResults) {
                        FeatureLayer feaLayer = null;
                        if (layerResult.getLayerContent() instanceof FeatureLayer) {
                            feaLayer = (FeatureLayer) layerResult.getLayerContent();
                        }
                         for (GeoElement identifiedElement : layerResult.getElements()) {
                            if (identifiedElement instanceof Feature) {
                                ArcGISFeature feature = (ArcGISFeature) identifiedElement;
                                if (feaLayer != null) {
                                    feaLayer.selectFeature(feature);
                                }

                                long layerId = feature.getFeatureTable().getServiceLayerId();
                                String layerName = feature.getFeatureTable().getTableName();
                                if (!layerMap.containsKey(layerName)) {
                                    List<Feature> results = new ArrayList<>();
                                    results.add(feature);
                                    layerMap.put(layerName, results);
                                }else {
                                    List<Feature> results = layerMap.get(layerName);
                                    if (results == null)
                                        results = new ArrayList<>();
                                    results.add(feature);
                                }
                            }
                        }
                    }
                    if (layerMap.size() > 0) {
                        if (param_value != null){
                            Bundle bundle = new Bundle();
                            bundle.putInt(QUERY_PIPE_BY_NAME_KEY, param_by.getIndex());
                            bundle.putStringArray(QUERY_PIPE_BY_VALUE_KEY, param_value);
                            sendResult(layerMap, QUERY_ONLINE_SUCCESS, bundle);
                        } else {
                            sendResult(layerMap, QUERY_ONLINE_SUCCESS);
                        }
                    } else {
                        sendResult("未点击到管线", QUERY_ONLINE_ERROR);
                    }
                } catch (InterruptedException | ExecutionException ex) {
                    sendResult(ex.getMessage(), QUERY_ONLINE_ERROR);
                }
            });
            /*final ServiceFeatureTable hydrantsTable = new ServiceFeatureTable(urlQuery);
            hydrantsTable.addDoneLoadingListener(() -> {
                *//*List<FeatureType> featureTypes = hydrantsTable.getFeatureTypes();
                GeometryType geometryType = hydrantsTable.getGeometryType();
                String tableName = hydrantsTable.getTableName();
                String sid = hydrantsTable.getObjectIdField();*//*
                QueryParameters queryParameters = new QueryParameters();
                queryParameters.setGeometry(geometry);
                final ListenableFuture<FeatureQueryResult> query = hydrantsTable.queryFeaturesAsync(queryParameters);
                query.addDoneListener(() -> {
                    try {
                        Map<String, List<Feature>> layerMap = new HashMap<>();
                        FeatureQueryResult result = query.get();
                        for (Feature feature: result) {
                            String layerId = feature.getFeatureTable().getLayer().getId();
                            String layerName = feature.getFeatureTable().getLayer().getName();
                            if (!layerMap.containsKey(layerId)) {
                                List<Feature> results = new ArrayList<>();
                                results.add(feature);
                                layerMap.put(layerName, results);
                            }else {
                                List<Feature> results = layerMap.get(layerId);
                                if (results == null)
                                    results = new ArrayList<>();
                                results.add(feature);
                            }
                        }
                        if (layerMap.size() > 0) {
                            sendResult(layerMap, QUERY_ONLINE_SUCCESS);
                        } else {
                            sendResult("未点击到管线", QUERY_ERROR);
                        }
                    }catch (Exception e){
                        sendResult(e.getMessage(), QUERY_ERROR);
                    }
                });
            });
            hydrantsTable.loadAsync();*/
        }).start();
    }

    public void query_pipe_1(android.graphics.Point screenPoint, MapView mapView) {
        query_pipe(screenPoint, mapView);
        mIsReturnAll = true;
    }

    public void query_pipe(final android.graphics.Point screenPoint, MapView mapView){
        mIsReturnAll = false;
        boolean onlineMap = UiMainLayerManagerDailog.isOnlineMap();
        if (onlineMap) {
            query_pipe_online_by_tap(screenPoint, mapView);
        }else {
            queryPipe(screenPoint, mapView);
        }
    }

    private void query_pipe_online(final android.graphics.Point screenPoint, MapView mapView){
        closeMapQueryView(mapView);

        if (progressDialog == null) {
            progressDialog = new ProgressDialog(mContext);
            progressDialog.setMessage("管网数据查询中...");
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }

        new Thread(() -> {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            ListenableFuture<List<IdentifyLayerResult>> identifyFuture =
                    mapView.identifyLayersAsync(screenPoint, 10, false, 10);
            identifyFuture.addDoneListener(() -> {
                try {
                    Map<String, List<Feature>> layerMap = new HashMap<>();
                    List<IdentifyLayerResult> layerResults = identifyFuture.get();
                    for (IdentifyLayerResult result : layerResults) {
                        List<IdentifyLayerResult> sublayerResults = result.getSublayerResults();
                        for (IdentifyLayerResult sublayerResult : sublayerResults) {
                            List<GeoElement> elements = sublayerResult.getElements();
                            for (GeoElement identifiedElement : elements) {
                                if (identifiedElement instanceof Feature) {
                                    ArcGISFeature feature = (ArcGISFeature) identifiedElement;
                                    String layerName = feature.getFeatureTable().getTableName();
                                    if (!layerMap.containsKey(layerName)) {
                                        List<Feature> results = new ArrayList<>();
                                        results.add(feature);
                                        layerMap.put(layerName, results);
                                    }else {
                                        List<Feature> results = layerMap.get(layerName);
                                        if (results == null)
                                            results = new ArrayList<>();
                                        results.add(feature);
                                    }
                                }
                            }
                        }
                    }
                    if (layerMap.size() > 0) {
                        sendResult(layerMap, QUERY_ONLINE_SUCCESS);
                    } else {
                        sendResult("未点击到管线", QUERY_ERROR);
                    }
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                    sendResult("未点击到管线", QUERY_ERROR);
                }
            });
        }).start();
    }

    /**
     * 查询设备
     * */
    public void queryDevice(Point point, int layerId, String keyword, MapServiceCallback serviceCallback) {
        String urlQuery = NetRequestURL.ONLINE_PIPE_INTERNAL + "/" + layerId;
        final UserBean userBean = BaseApp.getInstance().getLoginUser();
        if (userBean != null) {
            MAP_CODE_KEY MAP_PIPE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_PIPE.getCode());
            UserOnlineMapDataBean pipeDataBean =
                    dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_PIPE.getCode());
            if (pipeDataBean != null) {
                String pipe_url = pipeDataBean.getCval();
                if (pipe_url != null && !pipe_url.isEmpty()) {
                    urlQuery = NetRequestURL.getReplaceUrl(pipe_url) + "/" + layerId;
                }
            }
        }

        final ServiceFeatureTable hydrantsTable = new ServiceFeatureTable(urlQuery);
        hydrantsTable.loadAsync();
        hydrantsTable.addDoneLoadingListener(() -> {
            String where = "CODE like '%" + keyword + "%'";
            QueryParameters queryParameters = new QueryParameters();
            queryParameters.setWhereClause(where);
            if (point != null) {
                queryParameters.setGeometry(point);
            }
            final ListenableFuture<FeatureQueryResult> future = hydrantsTable.queryFeaturesAsync(queryParameters, ServiceFeatureTable.QueryFeatureFields.LOAD_ALL);
            future.addDoneListener(() -> {
                List<Feature> features = new ArrayList<>();
                try {
                    FeatureQueryResult queryResult = future.get();
                    for (GeoElement element : queryResult) {
                        if (element instanceof Feature) {
                            Feature feature = (Feature) element;
                            features.add(feature);
                        }
                    }
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }

                if (features.size() > 0) {
                    serviceCallback.onGetDevices(features);
                }else {
                    serviceCallback.onError("未查询到设备");
                }
            });
        });
    }

    // 签到后的 gps 轨迹图层
    public void loadSignPathLayer() {
        new Thread(() -> {
            String ymd = DateUtils.getYMD();
            long signSection = SharePreUtil.getSignSection(ymd);
            if (signSection < 0) {
                //sendResult(baseMapController.getString(R.string.no_sign_path), QUERY_ERROR);
                return;
            }
            List<LocationGPSDataBean> locationGPGSData = DBDaoHelper.getInstance()
                    .getTodayLocationGPSData(signSection);
            if (locationGPGSData != null) {
                if (locationGPGSData.size() > 0) {
                    GraphicsOverlay signLayer = new GraphicsOverlay();
                    MapView mapView = mapLoadHelper.getMapView();
                    if (mapView != null) {
                        PointCollection collection = new PointCollection(mapView.getSpatialReference());
                        for (Iterator<LocationGPSDataBean> iterator = locationGPGSData.iterator(); iterator.hasNext();) {
                            LocationGPSDataBean next = iterator.next();
                            Point screenPoint = new Point(next.getLongitude(), next.getLatitude());
                            signLayer.getGraphics().add(new Graphic(screenPoint, BaseMapController.mMarkerSymbol));
                            collection.add(screenPoint);
                        }
                        Polyline polyline = new Polyline(collection);
                        Graphic graphic = new Graphic(polyline, BaseMapController.mLineSymbol);
                        signLayer.getGraphics().add(graphic);
                        signGraphicId = signLayer.getGraphics().indexOf(graphic);
                        signPathLayer = signLayer;
                        sendResult(signLayer, SIGN_PATH);
                    }
                } else {
                    //sendResult(baseMapController.getString(R.string.no_sign_path), QUERY_ERROR);
                }
            } else {
                //sendResult(baseMapController.getString(R.string.no_sign_path), QUERY_ERROR);
            }
        }).start();
    }

    public void query_pipe_online(final Geometry geometry, final MapView mapView) {
        query_pipe_online(geometry, mapView, null, null);
    }

    public static final String[] TABLE_PIPE_NAME_CN = {"高压管线", "次高压管线", "中压管线", "低压管线"};

    public static final String[] TABLE_PIPE_IDS = {"11", "12", "13", "14"};

    public void query_pipe_online_byLayerName(final android.graphics.Point screenPoint, final MapView mapView, final String[] layerName) {
        mIsReturnAll = false;
        query_pipe_online(screenPoint, mapView, QUERY_PARAM_BY.QUERY_INDEX_LAYERNAME, layerName);
    }

    public void query_pipe_online_byLayerIDS(final android.graphics.Point screenPoint, final MapView mapView, final String[] layerIds) {
        mIsReturnAll = false;
        query_pipe_online(screenPoint, mapView, QUERY_PARAM_BY.QUERY_INDEX_LAYERID, layerIds);
    }

    enum QUERY_PARAM_BY{
        QUERY_INDEX_LAYERID(0),
        QUERY_INDEX_LAYERNAME(1);

        QUERY_PARAM_BY(int index){
            this.index = index;
        }

        public int getIndex() {
            return index;
        }

        private int index;
    }

    private static final String QUERY_PIPE_BY_NAME_KEY = "query_by_name";
    private static final String QUERY_PIPE_BY_VALUE_KEY = "query_by_value";
    public void query_pipe_online(final Geometry geometry, final MapView mapView, final QUERY_PARAM_BY param_by, final String param_value) {
        closeMapQueryView(mapView);

        if (progressDialog == null) {
            progressDialog = new ProgressDialog(mContext);
            progressDialog.setMessage("管网数据查询中...");
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }

        new Thread(() -> {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            String pipe_url = NetRequestURL.ONLINE_PIPE_INTERNAL;
            UserBean userBean = BaseApp.getInstance().getLoginUser();
            MAP_CODE_KEY MAP_PIPE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_PIPE.getCode());
            UserOnlineMapDataBean pipeDataBean =
                    dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_PIPE.getCode());
            if (pipeDataBean != null) {
                String cval = pipeDataBean.getCval();
                if (cval != null && !cval.isEmpty()){
                    pipe_url = NetRequestURL.getReplaceUrl(cval);
                }
            }

            final ServiceFeatureTable hydrantsTable = new ServiceFeatureTable(pipe_url);
            QueryParameters queryParameters = new QueryParameters();
            queryParameters.setGeometry(geometry);
            queryParameters.setMaxAllowableOffset(15);
            queryParameters.setReturnGeometry(true);
            if (param_by != null && param_by == QUERY_PARAM_BY.QUERY_INDEX_LAYERID){
                if (param_value != null && !param_value.isEmpty()) {
                    queryParameters.setWhereClause("pipeobjectid=" + param_value);
                }
            }
            final ListenableFuture<FeatureQueryResult> future = hydrantsTable.queryFeaturesAsync(queryParameters);
            future.addDoneListener(() -> {
                try {
                    FeatureQueryResult queryResult = future.get();
                    Map<String, List<Feature>> layerMap = new HashMap<>();
                    for (GeoElement identifiedElement : queryResult) {
                        if (identifiedElement instanceof Feature) {
                            ArcGISFeature feature = (ArcGISFeature) identifiedElement;
                            long layerId = feature.getFeatureTable().getServiceLayerId();
                            String layerName = feature.getFeatureTable().getTableName();
                            if (!layerMap.containsKey(layerName)) {
                                List<Feature> results = new ArrayList<>();
                                results.add(feature);
                                layerMap.put(layerName, results);
                            }else {
                                List<Feature> results = layerMap.get(layerName);
                                if (results == null)
                                    results = new ArrayList<>();
                                results.add(feature);
                            }
                        }
                    }
                    if (layerMap.size() > 0) {
                        if (param_value != null){
                            Bundle bundle = new Bundle();
                            bundle.putInt(QUERY_PIPE_BY_NAME_KEY, param_by.getIndex());
                            bundle.putString(QUERY_PIPE_BY_VALUE_KEY, param_value);
                            sendResult(layerMap, QUERY_ONLINE_SUCCESS, bundle);
                        }else {
                            sendResult(layerMap, QUERY_ONLINE_SUCCESS);
                        }
                    } else {
                        sendResult("未点击到管线", QUERY_ONLINE_ERROR);
                    }
                } catch (ExecutionException | InterruptedException e) {
                    sendResult(e.getMessage(), QUERY_ONLINE_ERROR);
                }
            });
        }).start();
    }

    public void query_pipe_online_layerid(final Geometry geometry, final MapView mapView, final String layerId, String[] fieldsReturn){
        UserBean userBean = BaseApp.getInstance().getLoginUser();
        MapUrlConfigDataBean mapUrlConfig = dbDaoHelper.getMapUrlConfig(userBean.getUserid());
        String urlQuery = NetRequestURL.ONLINE_PIPE_INTERNAL;
        if (mapUrlConfig != null && mapUrlConfig.getPipeurl() != null) {
            String pipe_url = mapUrlConfig.getPipeurl();
            if (pipe_url != null && !pipe_url.isEmpty()) {
                urlQuery = NetRequestURL.getMapQueryUrlHead() + pipe_url;
            }
        }
        urlQuery = urlQuery + "/" + layerId;
        query_pipe_online_layerid(geometry, mapView, urlQuery, null, fieldsReturn);
    }

    private static final String MUST_SHUT_LAYER_NAME = "Output Point";
    public void query_pipe_online_mustshut(final MapView mapView, ArcGISMapImageLayer layer){
        if (layer != null){
            String urlQuery = layer.getUri();
            ArcGISSublayer shutLayer = null;

            SublayerList sublayers = layer.getSublayers();
            for (ArcGISSublayer sublayer : sublayers) {
                if (sublayer.getName().equals(MUST_SHUT_LAYER_NAME)){
                    shutLayer = sublayer;
                    break;
                }
            }

            if (shutLayer != null){
                String sqlWhere = "mustshut=1";
                urlQuery = urlQuery + "/" + shutLayer.getId();
                //query_pipe_online_layerid(null, mapView, urlQuery, sqlWhere, null);
                query_pipe_must_shut(urlQuery);
            }
        }
    }

    private void query_pipe_must_shut(String urlQuery) {
        HttpUtil httpUtil = new HttpUtil(mContext);
        httpUtil.execute_get(urlQuery + "/query?f=json&outFields=*&where=mustshut=1", new PipeAnalyzeResultBottomSheet.GisCallback() {
            @Override
            public void success(String result) {
                List<PipeAnalyzeMustShutFeatureBean> featureBeans = null;
                try {
                    URLResponseCode.URLResponse responseCode = URLResponseCode.URLResponse.FastResponse(result);
                    String rowsArray = responseCode.queryResult("features");
                    Gson gson = new Gson();
                    featureBeans = gson.fromJson(rowsArray, new TypeToken<List<PipeAnalyzeMustShutFeatureBean>>(){}.getType());
                } catch (Exception e) {
                    e.printStackTrace();
                    sendResult("没有数据", QUERY_ONLINE_BY_KEY_ERROR);
                }
                if (featureBeans != null && featureBeans.size() > 0) {
                    sendResult(featureBeans, QUERY_ONLINE_BY_KEY_SUCCESS);
                } else {
                    sendResult("未点击到设备", QUERY_ONLINE_BY_KEY_ERROR);
                }
            }

            @Override
            public void error(String result) {
                sendResult("没有数据", QUERY_ONLINE_BY_KEY_ERROR);
            }

            @Override
            public void netError(String result) {
                sendResult("没有数据", QUERY_ONLINE_BY_KEY_ERROR);
            }
        });
    }

    public void query_pipe_online_layerid(final Geometry geometry, final MapView mapView, final String urlQuery, final String sqlWhere, final String[] fieldsReturn) {
        closeMapQueryView(mapView);

        if (progressDialog == null) {
            progressDialog = new ProgressDialog(mContext);
            progressDialog.setMessage("管网数据查询中...");
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }

        new Thread(() -> {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            final ServiceFeatureTable hydrantsTable = new ServiceFeatureTable(urlQuery);
            QueryParameters query = new QueryParameters();
            if (geometry != null){
                final int SCREEN_OFFSET = 100;
                android.graphics.Point point1 = mapView.locationToScreen((Point)geometry);
                double mapDistance = ArcgisUtils.distance2Map(mapView, point1, SCREEN_OFFSET);
                Polygon polygon = GeometryEngine.buffer(geometry, mapDistance);
                query.setGeometry(polygon);
            }

            if (sqlWhere != null && !sqlWhere.isEmpty()){
                query.setWhereClause(sqlWhere);
            }

            ServiceFeatureTable.QueryFeatureFields queryFields = ServiceFeatureTable.QueryFeatureFields.LOAD_ALL;
            if (fieldsReturn != null && fieldsReturn.length > 0)
                queryFields = ServiceFeatureTable.QueryFeatureFields.IDS_ONLY;

                final ListenableFuture<FeatureQueryResult> future = hydrantsTable.queryFeaturesAsync(query);
                future.addDoneListener(() -> {
                    FeatureQueryResult queryResult = null;
                    List<Feature> fetures = new ArrayList<>();
                    try {
                        queryResult = future.get();
                        for (GeoElement element : queryResult) {
                            if (element instanceof Feature) {
                                Feature f = (Feature) element;
                                fetures.add(f);
                            }
                        }
                    } catch (ExecutionException | InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (queryResult != null){
                        long count = fetures.size();
                        if (count > 0) {
                            sendResult(queryResult, QUERY_ONLINE_BY_KEY_SUCCESS);
                        } else {
                            sendResult("未点击到设备", QUERY_ONLINE_BY_KEY_ERROR);
                        }
                    }else {
                        sendResult("没有数据", QUERY_ONLINE_BY_KEY_ERROR);
                    }
                });
        }).start();
    }

    /**
     * 爆管分析
     *
     * @param point       分析的点
     * @param mapView     地图
     */
    private static final String usertoken_text = "usertoken";
    private static final String x_text = "x";
    private static final String y_text = "y";
    private static final String buffer_text = "buffer";
    private static final String summary_text = "summary";
    private static final String pipe_name_text = "pipefeatureclassname";
    private static final String pipe_name_value = "pipesectionmp";
    private static final String pipe_id_text = "pipeobjectid";
    private static final String outpoint_field_text = "outpointfields";
    private static final String outpoint_field_value = "sid";

    public enum ESRIJOBSTATUS {
        SUBMITTED("esriJobSubmitted"),
        SUCCEEDED("esriJobSucceeded"),
        FAILED("esriJobEFailed");

        ESRIJOBSTATUS(String status){
            jobStatus = status;
        }

        public String getStatus() {
            return jobStatus;
        }

        public static ESRIJOBSTATUS Status(String status){
            switch (status){
                case "esriJobSubmitted":
                    return SUBMITTED;
                case "esriJobSucceeded":
                    return SUCCEEDED;
                case "esriJobError":
                    return FAILED;
                default:
                    return SUBMITTED;
            }
        }

        final String jobStatus;
    }

    private PipeAnalyzeHttpTask mAnalyzeHttpTask = null;
    public void pipeHttpAnalysis(Context context, MapView mapView, String pipe_id, String layerDBName, Boolean bShowProgress, OnGetPipeJobMapResult onGetPipeJobMapResult) {
        closeMapQueryView(mapView);
        if (mAnalyzeHttpTask != null && !mAnalyzeHttpTask.isTaskFinished()){
            ToastUtil.showToast(context, "爆管分析正在进行中，请稍后...");
            return;
        }
        mAnalyzeHttpTask = new PipeAnalyzeHttpTask(context, mapView, pipe_id, layerDBName, bShowProgress, onGetPipeJobMapResult);
        mAnalyzeHttpTask.execute();
    }

    private class PipeAnalyzeHttpTask {
        private Context mContext;
        private MapView mapView;
        private String mPipeId;
        private String mLayerDBName;
        private PipeAnalysisResultBean resultBean = new PipeAnalysisResultBean();
        private OnGetPipeJobMapResult onGetPipeJobMapResult;
        private AlertDialog mProgressDialog = null;
        private boolean mbShowProgress;
        private boolean isJobFinished;
        private boolean isJobCancled;
        private boolean isTaskFinished;
        private boolean isGetJobResut;
        private  MapServiceTool mapServiceTool;
        private Timer analysisTimer = null;

        PipeAnalyzeHttpTask(Context context, MapView mapView, String pipe_id, String layerDBName, boolean bShowProgress, OnGetPipeJobMapResult onGetPipeJobMapResult) {
            this.mContext = context;
            this.mapView = mapView;
            this.mPipeId = pipe_id;
            this.mLayerDBName = layerDBName;
            this.onGetPipeJobMapResult = onGetPipeJobMapResult;
            this.mbShowProgress = bShowProgress;
            mapServiceTool = MapServiceTool.getInstance();
            isJobFinished = false;
            isJobCancled = false;
            isTaskFinished = false;
            isGetJobResut = false;
        }

        public boolean isTaskFinished() {
            return isTaskFinished;
        }

        public boolean isJobFinished() {
            return isJobFinished;
        }

        public boolean isJobFinished(PipeAnalyzeStatusBean statusBean) {
            ESRIJOBSTATUS status = ESRIJOBSTATUS.Status(statusBean.getJobStatus());
            if (status == ESRIJOBSTATUS.FAILED ||
                    status == ESRIJOBSTATUS.SUCCEEDED)
                return true;
            else
                return false;
        }

        public boolean isJobCancled() {
            return isJobCancled;
        }

        public void cancelJob() {
            if (mProgressDialog != null && mProgressDialog.isShowing())
                mProgressDialog.cancel();
            if (analysisTimer != null) {
                analysisTimer.cancel();
            }
            isJobFinished = true;
            isJobCancled = true;
            isTaskFinished = true;
        }

        void onPreExecute() {
            if (mbShowProgress)
                mProgressDialog = showPipeAnalyzeDialog(mContext, onGetPipeJobMapResult);
        }

        public void execute() {
            onPreExecute();

            resultBean.setCode(-1);
            resultBean.setError("没有获取到分析结果！");

            String gisToken = MapServiceTool.MAP_DEFAULT_GIS_TOKEN/*SharePreUtil.getGisToken(mContext)*/;
            mapServiceTool.submitPipeAnalyzeJob(mContext, gisToken, mPipeId, mLayerDBName, new MapServiceCallback(){
                @Override
                public void onSubmitPipeAnalyzeJobt(boolean isSuccess, int errorCode, String errMsg, String job_id) {
                    super.onSubmitPipeAnalyzeJobt(isSuccess, errorCode, errMsg, job_id);
                    if (isSuccess) {
                        checkJobStatus(job_id, new MapServiceCallback(){
                            @Override
                            public void onGetPipeAnalyzeJobStatus(boolean isSuccess, int errorCode, String errMsg, PipeAnalyzeStatusBean statusBean) {
                                super.onGetPipeAnalyzeJobStatus(isSuccess, errorCode, errMsg, statusBean);

                                getJobResult(job_id, errorCode, errMsg, statusBean, new MapServiceCallback(){
                                    @Override
                                    public void onGetPipeAnalyzeResult(boolean isSuccess, int errorCode, String errMsg, PipeAnalysisResultBean resultBean) {
                                        super.onGetPipeAnalyzeResult(isSuccess, errorCode, errMsg, resultBean);

                                        onPostExecute();
                                    }
                                });
                            }
                        });
                    }else {
                        resultBean.setCode(errorCode);
                        resultBean.setError(errMsg);

                        onPostExecute();
                    }
                }
            });
        }

        void checkJobStatus(String jobId, MapServiceCallback mapServiceCallback) {
            final String tag = "-pipeAnalyzeGetJobStatus";
            resultBean.setCode(-1);
            resultBean.setError("没有获取到分析结果！");

            try {
                if (!TextUtils.isEmpty(jobId)) {
                    analysisTimer = new Timer();
                    TimerTask jobStatusTask = new TimerTask() {
                        @Override
                        public void run() {
                            mapServiceTool.getPipeAnalyzeJobStatus(mContext, tag, jobId, new MapServiceCallback(){
                                @Override
                                public void onGetPipeAnalyzeJobStatus(boolean isSuccess, int errorCode, String errMsg, PipeAnalyzeStatusBean statusBean) {
                                    super.onGetPipeAnalyzeJobStatus(isSuccess, errorCode, errMsg, statusBean);

                                    if (isSuccess) {
                                        if (statusBean != null && isJobFinished(statusBean)) {
                                            isJobFinished = true;
                                            analysisTimer.cancel();
                                            BaseApp.cancelRequest(mContext.getClass().getName() + tag);
                                        }
                                    }

                                    if (isJobFinished && mapServiceCallback != null) {
                                        if (!isGetJobResut){
                                            mapServiceCallback.onGetPipeAnalyzeJobStatus(isSuccess, errorCode, errMsg, statusBean);
                                            isGetJobResut = true;
                                        }
                                    }
                                }
                            });
                        }
                    };
                    analysisTimer.schedule(jobStatusTask, 500, 2000);
                }
            } catch (Exception e) {
                resultBean.setCode(-1);
                resultBean.setError("解析异常！");
            }
        }

        void getJobResult(String jobId, int errorCode, String errMsg, PipeAnalyzeStatusBean statusBean, MapServiceCallback serviceCallback) {
            ESRIJOBSTATUS job_Status = ESRIJOBSTATUS.Status(statusBean.getJobStatus());
            switch (job_Status) {
                case FAILED: {
                    resultBean.setError(errMsg);
                    resultBean.setCode(errorCode);
                    serviceCallback.onGetPipeAnalyzeResult(false, errorCode, errMsg, resultBean);
                }
                break;
                case SUCCEEDED: {
                    String summary_url = statusBean.getResults().getSummary().getParamUrl();
                    mapServiceTool.getPipeAnalyzeResult(mContext, jobId, summary_url, new MapServiceCallback(){
                        @Override
                        public void onGetPipeAnalyzeResult(boolean isSuccess, int errorCode, String errMsg, PipeAnalysisResultBean bean) {
                            super.onGetPipeAnalyzeResult(isSuccess, errorCode, errMsg, bean);
                            if (isSuccess) {
                                resultBean = bean;
                                if (resultBean != null) {
                                    if (10000 == resultBean.getCode()) {
                                        resultBean.setJobId(jobId);
                                    } else {
                                        isSuccess = false;
                                    }
                                } else {
                                    isSuccess = false;
                                    resultBean.setCode(-1);
                                    resultBean.setError("没有获取到分析结果！");
                                }
                            }else {
                                resultBean.setCode(-1);
                                resultBean.setError("没有获取到分析结果！");
                            }
                            serviceCallback.onGetPipeAnalyzeResult(isSuccess, errorCode, errMsg, resultBean);
                        }
                    });
                }
                break;
                default: {
                    resultBean.setCode(-1);
                    resultBean.setError("没有获取到分析结果！");
                    serviceCallback.onGetPipeAnalyzeResult(false, errorCode, errMsg, resultBean);
                }
                break;
            }
        }

        void onPostExecute() {
            if (mProgressDialog != null && mProgressDialog.isShowing())
                mProgressDialog.cancel();

            PipeAnalysisResultBean bean = resultBean;
            if (bean.getCode() == 10000) {
                ToastUtil.showToast(mContext, bean.getMessage());
                pipeResultShowMap(bean, onGetPipeJobMapResult);
            } else {
                String errMsg = bean.getError() != null ? bean.getError().toString() : bean.getMessage();
                ToastUtil.showToast(mContext, errMsg);
                if (onGetPipeJobMapResult != null){
                    onGetPipeJobMapResult.onGetResult(false, null, null);
                }
            }

            isJobFinished = true;
            isTaskFinished = true;

        }
    }

    private PipeAnalyzeTask mAnalyzeTask = null;
    public void pipeAnalysis(Context context, MapView mapView, Point point, String pipe_id ,Boolean bShowProgress, OnGetPipeJobMapResult onGetPipeJobMapResult) {
        closeMapQueryView(mapView);
        if (mAnalyzeTask != null && !mAnalyzeTask.isJobFinished()){
            ToastUtil.showToast(context, "爆管分析正在进行中，请稍后...");
            return;
        }
        mAnalyzeTask = new PipeAnalyzeTask(context, mapView, point, pipe_id, bShowProgress, onGetPipeJobMapResult);
        mAnalyzeTask.execute();
    }

    private class PipeAnalyzeTask {
        private Context mContext;
        private MapView mapView;
        private Point mPoint;
        private String mPipeId;
        private PipeAnalysisResultBean resultBean = new PipeAnalysisResultBean();
        private GeoprocessingJob mGeoprocessJob = null;
        private OnGetPipeJobMapResult onGetPipeJobMapResult;
        private AlertDialog mProgressDialog = null;
        private boolean mbShowProgress;

        PipeAnalyzeTask(Context context, MapView mapView, Point point, String pipe_id, boolean bShowProgress, OnGetPipeJobMapResult onGetPipeJobMapResult) {
            this.mContext = context;
            this.mapView = mapView;
            this.mPoint = point;
            this.mPipeId = pipe_id;
            this.onGetPipeJobMapResult = onGetPipeJobMapResult;
            this.mbShowProgress = bShowProgress;
        }

        public boolean isJobFinished() {
            if (mGeoprocessJob == null)
                return true;

            Job.Status status = mGeoprocessJob.getStatus();
            return status == Job.Status.NOT_STARTED ||
                    status == Job.Status.SUCCEEDED ||
                    status == Job.Status.FAILED;
        }

        public void cancelJob() {
            if (mGeoprocessJob == null)
                return;

            mGeoprocessJob.cancel();
            mGeoprocessJob.addJobDoneListener(() -> {
                if (mProgressDialog != null && mProgressDialog.isShowing())
                    mProgressDialog.cancel();
                mGeoprocessJob = null;
            });
        }

        void onPreExecute() {
            if (mbShowProgress)
                mProgressDialog = showPipeAnalyzeDialog(mContext, onGetPipeJobMapResult);
        }

        public void execute() {
            onPreExecute();

            UserBean userBean = BaseApp.getInstance().getLoginUser();
            String gisToken = MapServiceTool.MAP_DEFAULT_GIS_TOKEN/*SharePreUtil.getGisToken(mContext)*/;
            GeoprocessingParameters geoproParameters = new GeoprocessingParameters(
                    GeoprocessingParameters.ExecutionType.ASYNCHRONOUS_SUBMIT);
            GeoprocessingString token = new GeoprocessingString(gisToken);
            geoproParameters.getInputs().put(usertoken_text, token);
            GeoprocessingString pipeName = new GeoprocessingString(pipe_name_value);
            geoproParameters.getInputs().put(pipe_name_text, pipeName);
/*            double x = mPoint.getX();
            GeoprocessingDouble paramsX = new GeoprocessingDouble(x);
            geoproParameters.getInputs().put(x_text, paramsX);
            double y = mPoint.getY();
            GeoprocessingDouble paramsY = new GeoprocessingDouble(y);
            geoproParameters.getInputs().put(y_text, paramsY);*/
            GeoprocessingString pipe_id = new GeoprocessingString(mPipeId);
            geoproParameters.getInputs().put(pipe_id_text, pipe_id);
            geoproParameters.setReturnM(false);
            geoproParameters.setReturnZ(false);

            String urlQuery = NetRequestURL.ONLINE_BURST_INTERNAL;
            MAP_CODE_KEY MAP_BURST = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_BURST.getCode());
            UserOnlineMapDataBean burstDataBean =
                    dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_BURST.getCode());
            if (burstDataBean != null) {
                String burst_url = burstDataBean.getCval();
                if (burst_url != null && !burst_url.isEmpty()){
                    urlQuery = NetRequestURL.getReplaceUrl(burst_url) /*+ "/submitJob"*/;
                }
            }

            resultBean.setCode(-1);
            resultBean.setError("没有获取到分析结果！");

            // create a job that will communicate with the GPServer
            GeoprocessingTask geoproTask = new GeoprocessingTask(urlQuery);
            GeoprocessingJob geoproJob = geoproTask.createJob(geoproParameters);
            mGeoprocessJob = geoproJob;

            // attach a listener to monitor result of the geoprocessing task
            geoproJob.addJobDoneListener(() -> {
                onPostExecute(geoproJob);
                mGeoprocessJob = null;
            });
            // start the job
            geoproJob.start();
        }

        void onPostExecute(GeoprocessingJob geoproJob) {
            if (mProgressDialog != null && mProgressDialog.isShowing())
                mProgressDialog.cancel();

            if (geoproJob.getStatus() == Job.Status.FAILED) {
                String errMsg = geoproJob.getError().getMessage();
                ToastUtil.showToast(mContext, errMsg);
                if (onGetPipeJobMapResult != null){
                    onGetPipeJobMapResult.onGetResult(false, null, null);
                }
            }else if (geoproJob.getStatus() == Job.Status.SUCCEEDED) {
                PipeAnalysisResultBean bean = process(geoproJob.getResult());
                if (bean.getCode() == 10000) {
                    ToastUtil.showToast(mContext, bean.getMessage());
                    pipeResultShowMap(bean, onGetPipeJobMapResult);
                } else {
                    String errMsg = bean.getError() != null ? bean.getError().toString() : bean.getMessage();
                    ToastUtil.showToast(mContext, errMsg);
                    if (onGetPipeJobMapResult != null){
                        onGetPipeJobMapResult.onGetResult(false, null, null);
                    }
                }
            }
        }
    }

    private  PipeAnalysisResultBean process(GeoprocessingResult geoprocessingResult) {
        final GeoprocessingString summary =
                (GeoprocessingString) geoprocessingResult.getOutputs().get(summary_text);

        PipeAnalysisResultBean resultBean;
        try {
            Gson gson = new Gson();
            resultBean = gson.fromJson(summary.getValue(), PipeAnalysisResultBean.class);
            if (resultBean != null) {
                if (10000 == resultBean.getCode()) {
                } else {

                }
            } else {
                resultBean = new PipeAnalysisResultBean();
                resultBean.setCode(-1);
                resultBean.setError("没有获取到分析结果！");
            }
        } catch (Exception e) {
            resultBean = new PipeAnalysisResultBean();
            resultBean.setCode(-1);
            resultBean.setError("解析异常！");
        }
        return resultBean;
    }

    public void pipeResultShowMap(PipeAnalysisResultBean resultBean, OnGetPipeJobMapResult onGetPipeJobMapResult) {
        PipeAnalyzeShowMapTask analyzeTask = new PipeAnalyzeShowMapTask(resultBean, onGetPipeJobMapResult);
        analyzeTask.execute();
    }

    private class PipeAnalyzeShowMapTask extends AsyncTask {
        private PipeAnalysisResultBean mResultBean;
        private OnGetPipeJobMapResult onGetPipeJobMapResult;
        private ArcGISMapImageLayer pipeLayer = null;

        PipeAnalyzeShowMapTask(PipeAnalysisResultBean resultBean, OnGetPipeJobMapResult onGetPipeJobMapResult){
            this.mResultBean = resultBean;
            this.onGetPipeJobMapResult = onGetPipeJobMapResult;
        }

        @Override
        protected Object doInBackground(Object[] objects) {
            long result = -1;
            UserBean userBean = BaseApp.getInstance().getLoginUser();
            String urlQuery = NetRequestURL.ONLINE_BURST_INTERNAL;
            UserOnlineMapDataBean.MAP_CODE_KEY MAP_BURST =
                    UserOnlineMapDataBean.MAP_CODE_KEY.Code(UserOnlineMapDataBean.MAP_CODE_KEY.MAP_CODE_BURST.getCode());
            UserOnlineMapDataBean burstDataBean =
                    dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_BURST.getCode());
            if (burstDataBean != null) {
                String burst_url = burstDataBean.getCval();
                if (burst_url != null && !burst_url.isEmpty()){
                    urlQuery = NetRequestURL.getReplaceUrl(burst_url);
                }
            }
            String job_url = NetRequestURL.getBurstJobUrl(urlQuery, mResultBean.getJobId());
            if (job_url != null){
                ArcGISMapImageLayer mapServiceLayer = new ArcGISMapImageLayer(job_url);
                mapServiceLayer.setOpacity(MAP_OPACITY);
                pipeLayer = mapServiceLayer;
                result = 0;
            }

            return result;
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
            boolean isSuccess = (long)o == 0 ? true : false;
            if (onGetPipeJobMapResult != null){
                onGetPipeJobMapResult.onGetResult(isSuccess, mResultBean, pipeLayer);
            }
        }
    }

    public interface OnGetPipeJobMapResult{
        void onGetJobHide();
        void onGetJobCanceled();
        void onGetResult(boolean isSuccess, PipeAnalysisResultBean resultBean, ArcGISMapImageLayer layer);
    }

    private AlertDialog showPipeAnalyzeDialog(Context context, final OnGetPipeJobMapResult onGetPipeJobMapResult) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setView(R.layout.analysis_dialog_content);
        AlertDialog dialog = builder.setNegativeButton("隐藏", (dialog1, which) -> {
            if (onGetPipeJobMapResult != null)
                onGetPipeJobMapResult.onGetJobHide();
            dialog1.dismiss();
        }).setNeutralButton("取消", (dialog12, which) -> {
            cancelAnalyzeTask();
            if (onGetPipeJobMapResult != null)
                onGetPipeJobMapResult.onGetJobCanceled();
            dialog12.dismiss();
        }).create();
        dialog.setCanceledOnTouchOutside(false);
        dialog.setCancelable(false);
        dialog.show();
        return dialog;
    }

    public void cancelAnalyzeTask(){
        if (mAnalyzeHttpTask != null && !mAnalyzeHttpTask.isJobFinished()){
            mAnalyzeHttpTask.cancelJob();
        }
    }

    public void query_device_by_sid(MapView mapView, final String sid){
        closeMapQueryView(mapView);

        if (progressDialog == null) {
            progressDialog = new ProgressDialog(mContext);
            progressDialog.setMessage("管网数据查询中...");
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }

        new Thread(() -> {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            String pipe_url = NetRequestURL.ONLINE_PIPE_INTERNAL;
            UserBean userBean = BaseApp.getInstance().getLoginUser();
            MAP_CODE_KEY MAP_PIPE = MAP_CODE_KEY.Code(MAP_CODE_KEY.MAP_CODE_PIPE.getCode());
            UserOnlineMapDataBean pipeDataBean =
                    dbDaoHelper.getUserOnlineMapData(userBean.getUserid(), MAP_PIPE.getCode());
            if (pipeDataBean != null) {
                String cval = pipeDataBean.getCval();
                if (cval != null && !cval.isEmpty()){
                    pipe_url = NetRequestURL.getReplaceUrl(cval);
                }
            }
            final ServiceFeatureTable hydrantsTable = new ServiceFeatureTable(pipe_url);
            final FeatureLayer featureLayer = new FeatureLayer(hydrantsTable);
            mapView.getMap().getOperationalLayers().add(featureLayer);
            featureLayer.loadAsync();
            hydrantsTable.addDoneLoadingListener(() -> {
                QueryParameters queryParameters = new QueryParameters();
                queryParameters.setReturnGeometry(true);
                queryParameters.setWhereClause("searchText=" + sid + "&layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26");
                final ListenableFuture<FeatureQueryResult> query = hydrantsTable.queryFeaturesAsync(queryParameters, ServiceFeatureTable.QueryFeatureFields.LOAD_ALL);
                query.addDoneListener(() -> {
                    try {
                        Map<String, List<Feature>> layerMap = new HashMap<>();
                        FeatureQueryResult result = query.get();
                        for (Feature feature: result) {
                            String layerId = feature.getFeatureTable().getLayer().getId();
                            String layerName = feature.getFeatureTable().getLayer().getName();
                            if (!layerMap.containsKey(layerId)) {
                                List<Feature> results = new ArrayList<>();
                                results.add(feature);
                                layerMap.put(layerName, results);
                            }else {
                                List<Feature> results = layerMap.get(layerId);
                                if (results == null)
                                    results = new ArrayList<>();
                                results.add(feature);
                            }
                        }
                        if (layerMap.size() > 0) {
                            sendResult(layerMap, QUERY_ONLINE_SUCCESS);
                        } else {
                            sendResult("未点击到管线", QUERY_ERROR);
                        }
                    }catch (Exception e){
                        sendResult(e.getMessage(), QUERY_ERROR);
                    }
                });
            });

        }).start();
    }

    private MapPointAnalyzeHttpTask mMapPointAnalyzeHttpTask = null;
    public void mapPointAnalyzeHttpTask(Context context, MapView mapView, String plan_id, String layerName, OnGetPipeJobMapResult onGetPipeJobMapResult) {
        closeMapQueryView(mapView);
        if (mMapPointAnalyzeHttpTask != null && !mMapPointAnalyzeHttpTask.isTaskFinished()){
            ToastUtil.showToast(context, "管线数据分析正在进行中，请稍后...");
            return;
        }
        List<String> PathIds = dbDaoHelper.getPlanOfflinePathId(plan_id);
        mMapPointAnalyzeHttpTask = new MapPointAnalyzeHttpTask(context, mapView, PathIds, layerName, onGetPipeJobMapResult);
        mMapPointAnalyzeHttpTask.execute();
    }

    public void cancelMapPointAnalyzeHttpTask() {
        if (mMapPointAnalyzeHttpTask != null) {
            mMapPointAnalyzeHttpTask.cancelJob();
        }
    }

    /*在线管线数据查询结果返回*/
    private void showOnlinePipeQueryResult(boolean success, String errStr, Object results) {
        Activity activity = (Activity) mContext;
        if (activity.isFinishing() || activity.isDestroyed()) {
            return;
        }

        if (onlineQueryWithKeyCallback != null){
            if (success){
                if (results != null) {
                    onlineQueryWithKeyCallback.showOnlineReuslt(true, errStr, results);
                }else {
                    onlineQueryWithKeyCallback.showOnlineReuslt(false, null, null);
                }
            }else {
                onlineQueryWithKeyCallback.showOnlineReuslt(false, errStr, null);
            }
        }
    }

    private void sendResult(Object result, int what) {
        Message msg = Message.obtain();
        msg.obj = result;
        msg.what = what;
        handler.sendMessage(msg);
    }

    private void sendResult(Object result, int what, Bundle bundle) {
        Message msg = Message.obtain();
        msg.obj = result;
        msg.what = what;
        msg.setData(bundle);
        handler.sendMessage(msg);
    }


    public List<FeatureLayer> getAllFeatureLayer(MapView mapView) {
        ArcGISMap arcMap = mapView.getMap();
        List<FeatureLayer> featureLayers = new ArrayList<>();
        LayerList layers = arcMap.getOperationalLayers();
        for (Layer layer : layers) {
            if (layer instanceof FeatureLayer) {
                FeatureLayer fl = (FeatureLayer) layer;
                featureLayers.add(fl);
            }
        }
        return featureLayers;
    }

    public void clearAllSeletction() {
        MapView mapView = getMapView();
        List<FeatureLayer> allFeatureLayer = getAllFeatureLayer(mapView);
        if (allFeatureLayer != null && allFeatureLayer.size() > 0) {
            for (FeatureLayer fl : allFeatureLayer) {
                fl.clearSelection();
            }
        }
    }

    public List<FeatureTable> getAllFeatureTable(MapView mapView) {
        ArcGISMap arcMap = mapView.getMap();
        LayerList layers = arcMap.getOperationalLayers();
        List<FeatureTable> featureTables = new ArrayList<>();
        for (Layer layer : layers) {
            if (layer instanceof FeatureLayer) {
                FeatureLayer fl = (FeatureLayer) layer;
                FeatureTable ft = fl.getFeatureTable();
                if (ft != null)
                    featureTables.add(ft);
            }
        }
        return featureTables;
    }

    //地图移动
    private void zoomToScale(MapView mapView, Geometry geometry, double scale) {
        if (geometry == null)
            return;

        Point point = (Point) geometry;
        mapView.setViewpointCenterAsync(point, scale); // TODO: 2016/10/5 离线地图校准后检查离线地图定位结果
    }

}


