com.palmaplus.activity.MapDetailActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.palmaplus.activity.MapDetailActivity.java

Source

package com.palmaplus.activity;

import android.annotation.SuppressLint;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.palmap.widget.Compass;
import com.palmap.widget.Scale;
import com.palmaplus.adapter.DynamicNavigateAdapter;
import com.palmaplus.adapter.FloorAdapter;
import com.palmaplus.app.R;
import com.palmaplus.base.BaseActivity;
import com.palmaplus.base.NagrandApplication;
import com.palmaplus.constants.Constant;
import com.palmaplus.event.SearchResultEvent;
import com.palmaplus.nagrand.core.Engine;
import com.palmaplus.nagrand.core.Types;
import com.palmaplus.nagrand.data.BasicElement;
import com.palmaplus.nagrand.data.CategoryModel;
import com.palmaplus.nagrand.data.DataSource;
import com.palmaplus.nagrand.data.Feature;
import com.palmaplus.nagrand.data.FeatureCollection;
import com.palmaplus.nagrand.data.FloorModel;
import com.palmaplus.nagrand.data.LocationList;
import com.palmaplus.nagrand.data.LocationModel;
import com.palmaplus.nagrand.data.LocationPagingList;
import com.palmaplus.nagrand.data.MapElement;
import com.palmaplus.nagrand.data.MapModel;
import com.palmaplus.nagrand.data.Param;
import com.palmaplus.nagrand.data.PlanarGraph;
import com.palmaplus.nagrand.geos.Coordinate;
import com.palmaplus.nagrand.geos.GeometryFactory;
import com.palmaplus.nagrand.geos.Point;
import com.palmaplus.nagrand.navigate.ConnectedInfo;
import com.palmaplus.nagrand.navigate.DynamicNavigateParams;
import com.palmaplus.nagrand.navigate.DynamicNavigateWrapper;
import com.palmaplus.nagrand.navigate.DynamicNavigationMode;
import com.palmaplus.nagrand.navigate.LineMode;
import com.palmaplus.nagrand.navigate.NavigateManager;
import com.palmaplus.nagrand.navigate.OnDynamicNavigateListener;
import com.palmaplus.nagrand.navigate.StepInfo;
import com.palmaplus.nagrand.position.Location;
import com.palmaplus.nagrand.position.PositioningManager;
import com.palmaplus.nagrand.position.ble.BeaconPositioningManager;
import com.palmaplus.nagrand.position.ble.utils.BleLocation;
import com.palmaplus.nagrand.position.util.PositioningUtil;
import com.palmaplus.nagrand.view.MapView;
import com.palmaplus.nagrand.view.adapter.DataListAdapter;
import com.palmaplus.nagrand.view.gestures.OnSingleTapListener;
import com.palmaplus.nagrand.view.gestures.OnZoomListener;
import com.palmaplus.nagrand.view.layer.FeatureLayer;
import com.palmaplus.utils.DisplayUtils;
import com.palmaplus.utils.LogUtils;
import com.palmaplus.utils.ToastUtils;
import com.palmaplus.vo.FeatureWrapper;
import com.palmaplus.vo.LocationWrapper;
import com.palmaplus.widget.CommonDialog;
import com.palmaplus.widget.Mark;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import in.workarounds.bundler.Bundler;
import in.workarounds.bundler.annotations.Arg;
import in.workarounds.bundler.annotations.RequireBundler;
import in.workarounds.bundler.annotations.Required;
import in.workarounds.bundler.annotations.State;

/**
 * Created by lchad on 2016/11/2.
 * Github: https://github.com/lchad
 */
@RequireBundler
public class MapDetailActivity extends BaseActivity implements View.OnClickListener {

    /**
     * id.
     */
    @Arg
    @Required
    @State
    long mMapId;

    @BindView(R.id.map_view)
    MapView mMapView;
    /**
     * 
     */
    @BindView(R.id.map_overlay_container)
    RelativeLayout mMapOverlayContainer;
    /**
     * 
     */
    @BindView(R.id.compass)
    Compass mCompass;
    /**
     * 
     */
    @BindView(R.id.architect)
    Scale mArchitect;
    @BindView(R.id.expand_arrow)
    ImageView mExpandArrow;
    @BindView(R.id.poi_name)
    TextView mPoiNameText;
    @BindView(R.id.category_text)
    TextView mCategoryText;
    @BindView(R.id.shop_info_container)
    RelativeLayout mPoiInfoContainer;
    @BindView(R.id.select_text)
    TextView mSelectText;
    @BindView(R.id.set_start)
    TextView mSetStart;
    @BindView(R.id.bottom_close)
    ImageView mBottomClose;
    @BindView(R.id.distance)
    TextView mDistanceText;
    @BindView(R.id.time)
    TextView mTimeText;
    @BindView(R.id.distance_time_container)
    RelativeLayout mDistanceTimeContainer;
    @BindView(R.id.blue_circle)
    ImageView mBlueGoThere;
    @BindView(R.id.base_bottom_container)
    RelativeLayout mBaseBottomContainer;
    @BindView(R.id.locate)
    ImageView mLocateOnOff;
    @BindView(R.id.title_icon_left)
    ImageView mTitleIconLeft;
    @BindView(R.id.title)
    TextView mTitle;
    @BindView(R.id.title_icon_right)
    ImageView mTitleIconRight;
    @BindView(R.id.title_right)
    TextView mTitleRight;
    @BindView(R.id.btn_floor)
    Button mBtnFloor;
    @BindView(R.id.floor)
    RecyclerView mFloorRecyclerView;
    @BindView(R.id.clear_nav_line)
    TextView mClearNavLine;

    @BindView(R.id.btn_select_transient)
    ImageView mBtnSelectTransient;
    @BindView(R.id.transient_container)
    LinearLayout mTransientContainer;
    @BindView(R.id.transient_add_bath)
    ImageView mTransientAddBath;
    @BindView(R.id.transient_add_atm)
    ImageView mTransientAddAtm;
    @BindView(R.id.transient_icon_container)
    LinearLayout mTransientIconContainer;
    @BindView(R.id.transient_clear_container)
    LinearLayout mTransientClearContainer;
    @BindView(R.id.through_container)
    LinearLayout mThroughContainer;
    @BindView(R.id.zoom_in)
    ImageView mZoomIn;
    @BindView(R.id.zoom_out)
    ImageView mZoomOut;
    @BindView(R.id.start_locate_text)
    TextView mStartLocateText;
    @BindView(R.id.end_locate_text)
    TextView mEndLocateText;
    @BindView(R.id.bottom_info_container)
    RelativeLayout mBottomInfoContainer;
    @BindView(R.id.view_pager)
    ViewPager mViewPager;
    @BindView(R.id.dynamic_navi_info_text)
    TextView mDynamicInfoText;
    @BindView(R.id.dynamic_container)
    LinearLayout mDynamicContainer;
    @BindView(R.id.iv_close_navi)
    ImageView mIvCloseNavi;
    @BindView(R.id.quit_navi)
    TextView mQuitNavi;
    @BindView(R.id.quit_navi_container)
    RelativeLayout mQuitNaviContainer;
    @BindView(R.id.dynamic_mode)
    ImageButton mDynamicNaviMode;
    @BindView(R.id.zoom_container)
    LinearLayout mZoomContainer;

    private DynamicNavigateAdapter mDynamicNavigateAdapter;
    /**
     * ??.
     */
    private List<StepInfo> mDynamicStepInfoList;

    /**
     * .
     */
    private List<Mark> mMarkList;
    /**
     * ?container.
     */
    private int mBaseBottomContainerHeight;
    /**
     * ?id.
     */
    private long mCurrentFloorId;

    private FloorAdapter mFloorAdapter;
    /**
     * 
     */
    private List<LocationModel> mFloorList;
    /**
     * ?feature.
     */
    private Feature selectedFeature;
    /**
     * 
     */
    private Mark mEndMark;
    /**
     * 
     */
    private Mark mStartMark;
    /**
     * ??
     */
    private Mark mTransientMark;
    /**
     * ?
     */
    private NavigateManager mNavigateManager;
    /**
     * 
     */
    private FeatureLayer mNavFeatureLayer;
    /**
     * ???
     */
    private BeaconPositioningManager mBeaconPositioningManager;
    /**
     * ?
     */
    private FeatureLayer mPositioningLayer;
    /**
     * ??
     */
    private double mGoTherePixelX;
    private double mGoTherePixelY;
    /**
     * ???
     */
    private boolean mCanSelectPoint = false;
    /**
     * ???atm(?)
     */
    private boolean mHasShowAllAtm = false;
    /**
     * ???(?)
     */
    private boolean mHasShowAllBath = false;
    /**
     * ????
     */
    private boolean mIsFetchingTransientNavData = false;
    /**
     * ???
     */
    private boolean mHasDrawTransientMavLine = false;
    /**
     * ???
     */
    private boolean mHasDrawNavLine = false;
    /**
     * ????
     */
    private Types.Point mTransientWorldPoint;
    /**
     * RecyclerView?item?.
     */
    private int mPastVisibleItemCount;
    /**
     * RecyclerView??item?
     */
    private int mVisibleItemCount;
    /**
     * RecyclerViewitem?
     */
    private int mTotalItemCount;
    /**
     * RecyclerView?
     */
    private boolean isEnd = true;

    /**
     * ?poi
     */
    private long mMapPoi;

    /**
     * ???native?,??.
     */
    private DataListAdapter<LocationModel> mDeprecatedAdapter;

    /**
     * ????poi?.
     */
    private LocationModel mNearByPoi;
    /**
     * ??.
     */
    private ConnectedInfo[] mNavigationConnectInfo;

    /**
     * ?mark
     */
    private List<Mark> mConnectMarkList = new ArrayList<>();

    /**
     * ??map
     */
    private Map<Long, String> mConnectMap;
    /**
     * ?????.
     */
    private boolean mHasLocated = false;
    /**
     * ??.
     */
    private BleLocation mCurrentBleLocation;
    /**
     * ????id.
     */
    private long mLocateFloorId = -1;
    /**
     * ????.
     */
    private DynamicNavigateParams mDynamicNavigateParams;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_map_detail;
    }

    @Override
    protected void initInject() {
        Bundler.inject(this);
        EventBus.getDefault().register(this);
        mMarkList = new ArrayList<>();
        mBaseBottomContainerHeight = DisplayUtils.dp2Px(mPoiNameText.getContext(), 86.5f);
        initConnectCate();
    }

    @Override
    protected void setView() {
        mDynamicStepInfoList = new ArrayList<>();

        mDynamicNavigateAdapter = new DynamicNavigateAdapter(MapDetailActivity.this, mDynamicStepInfoList);
        mViewPager.setAdapter(mDynamicNavigateAdapter);
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                Coordinate start = mDynamicStepInfoList.get(position).mStartPoint;
                Coordinate end = mDynamicStepInfoList.get(position).mEndPoint;
                if (start.getX() == 0 || start.getY() == 0 || end.getX() == 0 || end.getY() == 0) {
                    return;
                }
                mMapView.moveToRect(start.getX(), start.getY(), end.getX(), end.getY(), true, 300);
                LogUtils.d("mooooveto" + start.getX() + " " + start.getY() + " " + end.getX() + " " + end.getY());
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

        mMapView.start();
        mMapView.setMaxZoomLevel(12);
        mMapView.setMinZoomLevel(2);
        //        mMapView.setMaxAngle(90);
        //        mMapView.setMinAngle(30);
        mMapView.initRatio(0.67f);
        mMapView.setOnMapViewStatusChangedListener(new MapView.OnMapViewStatusListener() {
            @Override
            public void onMapViewStatus(MapView mapView, MapView.MapViewStatus mapViewStatus,
                    MapView.MapViewStatus mapViewStatus1) {

            }
        });

        mTitleIconRight.setVisibility(View.VISIBLE);
        mTitleIconRight.setImageResource(R.drawable.icon_nav_search_white);
        mTitleIconRight.setOnClickListener(this);

        mArchitect.setMapView(mMapView);
        mCompass.setMapView(mMapView);
        mMapView.setMapOptions(mMapOptions);
        mMapView.setOverlayContainer(mMapOverlayContainer);

        mExpandArrow.setOnClickListener(this);
        mBlueGoThere.setOnClickListener(this);
        mSetStart.setOnClickListener(this);
        mClearNavLine.setOnClickListener(this);
        mLocateOnOff.setOnClickListener(this);
        mBtnSelectTransient.setOnClickListener(this);
        mTransientClearContainer.setOnClickListener(this);
        mTransientIconContainer.setOnClickListener(this);
        mTransientContainer.setOnClickListener(this);
        mTransientAddAtm.setOnClickListener(this);
        mTransientAddBath.setOnClickListener(this);
        mBtnFloor.setOnClickListener(this);
        mCompass.setOnClickListener(this);
        mZoomIn.setOnClickListener(this);
        mZoomOut.setOnClickListener(this);
        mBaseBottomContainer.setOnClickListener(this);
        mBottomInfoContainer.setOnClickListener(this);
        mIvCloseNavi.setOnClickListener(this);
        mQuitNavi.setOnClickListener(this);
        mDynamicNaviMode.setOnClickListener(this);

        showProgressDialog();

        //zoom?
        mMapView.setOnZoomListener(new OnZoomListener() {
            @Override
            public void preZoom(MapView mapView, float x, float y) {

            }

            @Override
            public void onZoom(MapView mapView, boolean b) {

            }

            @Override
            public void postZoom(MapView mapView, float x, float y) {
                mCompass.invalidate();
                mArchitect.invalidate();
            }
        });

        //??
        mMapView.setOnSingleTapListener(new OnSingleTapListener() {
            @Override
            public void onSingleTap(MapView mapView, float x, float y) {
                if (mFloorRecyclerView.getVisibility() == View.VISIBLE) {
                    mFloorRecyclerView.setVisibility(View.GONE);
                }
                //??container?,???.
                if (mThroughContainer.getVisibility() == View.VISIBLE) {
                    mThroughContainer.setVisibility(View.GONE);
                    mBtnSelectTransient.setSelected(false);
                    return;
                }
                //?.
                if (mHasLocated) {
                    selectedFeature = mMapView.selectFeature(x, y);
                    Types.Point point = mMapView.converToWorldCoordinate(x, y);
                    if (selectedFeature != null) {
                        if (mEndMark != null) {
                            mMapView.removeOverlay(mEndMark);
                            mEndMark = null;
                        }
                        mEndMark = createMark("", mCurrentFloorId, point.x, point.y, true, R.drawable.icon_end);
                        mEndMark.setFloorText(mBtnFloor.getText().toString());
                        mEndMark.setLocationText(LocationModel.name.get(selectedFeature));
                        mapView.addOverlay(mEndMark);
                        showSelectedPoiInfo(selectedFeature, x, y);

                        if (mStartMark != null) {
                            mMapView.removeOverlay(mStartMark);
                            mStartMark = null;
                        }
                        mStartMark = new Mark(MapDetailActivity.this);
                        mStartMark.setLocationText(getString(R.string.my_location));
                        mBlueGoThere.setVisibility(View.VISIBLE);
                    } else {
                        hideBottomContainer();
                        mMapView.removeOverlay(mEndMark);
                    }
                    return;
                }

                //
                if (mEndMark != null && mStartMark != null && (mHasDrawNavLine || mHasDrawTransientMavLine)) {
                    if (mHasDrawNavLine) {//
                        if (mCanSelectPoint) {
                            //??
                            mTransientWorldPoint = mMapView.converToWorldCoordinate(x, y);

                            Coordinate[] coordinates = new Coordinate[] {
                                    new Coordinate(mTransientWorldPoint.x, mTransientWorldPoint.y) };
                            //??
                            mNavigateManager.navigation(mStartMark.getCoo(), mStartMark.getFloorId(),
                                    mEndMark.getCoo(), mEndMark.getFloorId(), coordinates,
                                    new long[] { mCurrentFloorId });
                            mIsFetchingTransientNavData = true;
                            return;
                        } else {
                            if (mClearNavLine.getVisibility() == View.VISIBLE) {//???
                                mClearNavLine.setVisibility(View.GONE);
                                mDistanceTimeContainer.setVisibility(View.VISIBLE);
                                mClearNavLine.setVisibility(View.GONE);
                                return;
                            }
                        }
                    }
                    if (mHasDrawTransientMavLine) {
                        if (mClearNavLine.getVisibility() == View.VISIBLE) {//???
                            mClearNavLine.setVisibility(View.GONE);
                            mDistanceTimeContainer.setVisibility(View.VISIBLE);
                            mClearNavLine.setVisibility(View.GONE);
                            return;
                        }
                    }
                    //
                    mClearNavLine.setVisibility(View.VISIBLE);
                    mDistanceTimeContainer.setVisibility(View.GONE);
                    mPoiInfoContainer.setVisibility(View.GONE);
                    mSetStart.setVisibility(View.GONE);
                    return;
                }

                //,?
                if (mEndMark != null && mStartMark != null) {
                    Types.Point point = mMapView.converToWorldCoordinate(x, y);

                    selectedFeature = mMapView.selectFeature(x, y);
                    if (selectedFeature != null) {
                        mMapView.removeOverlay(mStartMark);
                        mStartMark = null;
                        mStartMark = createMark("", mCurrentFloorId, point.x, point.y, true, R.drawable.icon_start);
                        mStartMark.setFloorText(mBtnFloor.getText().toString());
                        mStartMark.setLocationText(LocationModel.name.get(selectedFeature));
                        mapView.addOverlay(mStartMark);
                        mBlueGoThere.setVisibility(View.GONE);
                        showSelectedPoiInfo(selectedFeature, x, y);
                    } else {
                        mMapView.removeOverlay(mStartMark);
                        mStartMark = null;
                        hideBottomContainer();
                        mPoiNameText.setText("");
                    }
                    return;
                }

                //?
                if (mStartMark == null && mEndMark != null) {
                    selectedFeature = mapView.selectFeature(x, y);
                    if (selectedFeature == null) {
                        hideBottomContainer();
                        mEndMark = null;
                        mMapView.removeAllOverlay();
                        mPoiNameText.setText("");
                        mCategoryText.setText("");
                        mBlueGoThere.setVisibility(View.VISIBLE);
                        mSelectText.setVisibility(View.GONE);
                        return;
                    } else {
                        if (mStartMark != null) {
                            mMapView.removeOverlay(mStartMark);
                        }
                        Types.Point point = mMapView.converToWorldCoordinate(x, y);

                        mStartMark = createMark("", mCurrentFloorId, point.x, point.y, true, R.drawable.icon_start);
                        mStartMark.setFloorText(mBtnFloor.getText().toString());
                        if (selectedFeature != null) {
                            mStartMark.setLocationText(LocationModel.name.get(selectedFeature));
                        }
                        mapView.addOverlay(mStartMark);
                        mSetStart.setVisibility(View.VISIBLE);
                        mBlueGoThere.setVisibility(View.GONE);

                        showSelectedPoiInfo(selectedFeature, x, y);
                    }
                    return;
                }

                //
                if (mStartMark == null) {
                    if (mBaseBottomContainer.getVisibility() == View.GONE) {
                        mBaseBottomContainer.setVisibility(View.VISIBLE);
                    }
                    mGoTherePixelX = x;
                    mGoTherePixelY = y;

                    //??
                    if (selectedFeature != null) {
                        //
                        Feature feature = mapView.selectFeature(x, y);
                        if (feature != null) {
                            //?
                            mMapView.removeAllOverlay();

                            selectedFeature = feature;
                            showSelectedPoiInfo(selectedFeature, x, y);

                            Types.Point point = mMapView.converToWorldCoordinate(x, y);

                            Mark mark = createMark("", mCurrentFloorId, point.x, point.y, true,
                                    R.drawable.icon_marker);
                            mapView.addOverlay(mark);
                            //                            mMapView.setRenderableColor("Area", LocationModel.mMapId.get(selectedFeature), 0xffff5722);
                            showSelectedPoiInfo(selectedFeature, x, y);
                            mBlueGoThere.setVisibility(View.VISIBLE);
                        } else {
                            mMapView.removeAllOverlay();
                            hideBottomContainer();
                            selectedFeature = null;
                        }
                    } else {
                        //?
                        Feature feature = mapView.selectFeature(x, y);
                        if (feature == null) {
                            selectedFeature = null;
                            hideBottomContainer();
                        } else {
                            mMapView.removeAllOverlay();
                            selectedFeature = feature;
                            Types.Point point = mMapView.converToWorldCoordinate(x, y);

                            Mark mark = createMark("", mCurrentFloorId, point.x, point.y, true,
                                    R.drawable.icon_marker);
                            mapView.addOverlay(mark);
                            showSelectedPoiInfo(selectedFeature, x, y);
                            mBlueGoThere.setVisibility(View.VISIBLE);
                        }
                    }

                }
            }
        });
    }

    private void positionBaseContainer(int height) {
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                mBaseBottomContainerHeight);
        params.bottomMargin = height;
        params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        mBaseBottomContainer.setLayoutParams(params);
    }

    /**
     * ??
     */
    private void hideBottomContainer() {
        mBlueGoThere.setVisibility(View.GONE);
        positionBaseContainer(-mBaseBottomContainerHeight);
    }

    /**
     * 
     */
    private void showBottomContainer() {
        positionBaseContainer(0);
    }

    /**
     * ?,POI?
     */
    private void showSelectedPoiInfo(Feature feature, double pixelX, double pixelY) {
        mSelectText.setVisibility(View.GONE);
        //??,?""
        mCategoryText.setText("");
        //LocationModel?Featurename
        String name = null;
        long category = 0;
        if (feature != null) {
            name = LocationModel.name.get(feature);
            category = LocationModel.category.get(feature);
        }
        if (mDataSource == null) {
            return;
        }
        mPoiNameText.setText(name);

        if (category != 0) {
            mDataSource.requestCategory(category, new DataSource.OnRequestDataEventListener<CategoryModel>() {
                @Override
                public void onRequestDataEvent(DataSource.ResourceState resourceState,
                        CategoryModel categoryModel) {
                    if (resourceState != DataSource.ResourceState.ok) {
                        return;
                    }
                    final String cate = CategoryModel.NAME3.get(categoryModel);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mCategoryText.setText(cate);
                            if (TextUtils.isEmpty(mPoiNameText.getText().toString())) {
                                mPoiNameText.setText(cate);
                            }
                        }
                    });
                }
            });
        } else {
            Types.Point point = mMapView.converToWorldCoordinate(pixelX, pixelY);
            mDataSource.search("", 0, 10, new long[] { mCurrentFloorId }, new long[] {},
                    new Coordinate(point.x, point.y), 5,
                    new DataSource.OnRequestDataEventListener<LocationPagingList>() {
                        @Override
                        public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                LocationPagingList locationPagingList) {
                            if (locationPagingList == null || locationPagingList.getSize() == 0) {
                                mPoiNameText.setText(mBtnFloor.getText().toString());
                                return;
                            }

                            String poiName = "";
                            long poiCategory = 0;
                            for (int i = 0; i < locationPagingList.getSize(); i++) {
                                final LocationModel model = locationPagingList.getPOI(i);
                                Feature feature1 = mMapView.selectFeature(LocationModel.id.get(model));
                                poiCategory = LocationModel.category.get(feature1);
                                if (poiCategory != 0) {
                                    mNearByPoi = model;
                                    poiName = LocationModel.name.get(model);
                                    break;
                                }
                            }
                            final String finalPoiName = poiName;
                            if (poiCategory != 0) {
                                mDataSource.requestCategory(poiCategory,
                                        new DataSource.OnRequestDataEventListener<CategoryModel>() {
                                            @Override
                                            public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                                    CategoryModel categoryModel) {
                                                if (categoryModel == null) {
                                                    return;
                                                }
                                                mCategoryText.setText(CategoryModel.NAME3.get(categoryModel));
                                                if (TextUtils.isEmpty(finalPoiName)) {
                                                    mPoiNameText.setText(CategoryModel.NAME3.get(categoryModel) + ""
                                                            + getString(R.string.nearby));
                                                } else {
                                                    mPoiNameText.setText(
                                                            finalPoiName + "" + getString(R.string.nearby));
                                                }
                                            }
                                        });
                            }
                        }
                    });
        }

        mBaseBottomContainer.setVisibility(View.VISIBLE);
        showBottomContainer();
        mPoiInfoContainer.setVisibility(View.VISIBLE);
        mClearNavLine.setVisibility(View.GONE);
        mExpandArrow.setVisibility(View.VISIBLE);
    }

    public void afterDrawPlanarGraph() {
        mPositioningLayer = new FeatureLayer("positioning"); //?
        mMapView.addLayer(mPositioningLayer); // MapView
        mMapView.setLayerOffset(mPositioningLayer); // ??????

        // PositionLayer??
        Point point = GeometryFactory.createPoint(new Coordinate(0, 0));
        MapElement mapElement = new MapElement();
        mapElement.addElement("id", new BasicElement(1L)); // 1L?ID??
        Feature feature = new Feature(point, mapElement);
        mPositioningLayer.addFeature(feature);
    }

    @Override
    protected void initData() {
        String appKey = NagrandApplication.instance.getAppKey();
        if (TextUtils.isEmpty(appKey)) {
            return;
        }
        Engine engine = Engine.getInstance();
        engine.startWithLicense(appKey, MapDetailActivity.this);
        mDataSource = new DataSource(Constant.SERVER_URL);
        mNavigateManager = new NavigateManager(Constant.SERVER_URL);
        mNavigateManager.setOnDynamicNavigateListener(new OnDynamicNavigateListener() {
            @Override
            public void onNavigate(boolean b, DynamicNavigateWrapper wrapper) {
                if (wrapper != null && wrapper.mDynamicNavigateOutput != null) {
                    LogUtils.d("mDynamicNavigateOperate mLengthToNextStep: "
                            + wrapper.mDynamicNavigateOutput.mLengthToNextStep);
                    LogUtils.d("mDynamicNavigateOperate mDynamicNaviExplain: "
                            + wrapper.mDynamicNavigateOutput.mDynamicNaviExplain);
                    LogUtils.d(
                            "mDynamicNavigateOperate mMinDistance: " + wrapper.mDynamicNavigateOutput.mMinDistance);
                    LogUtils.d("mDynamicNavigateOperate mPassedLength: "
                            + wrapper.mDynamicNavigateOutput.mPassedLength);
                    LogUtils.d("mDynamicNavigateOperate mRemainingLength: "
                            + wrapper.mDynamicNavigateOutput.mRemainingLength);
                    LogUtils.d("mDynamicNavigateOperate mClipCoordinate: "
                            + wrapper.mDynamicNavigateOutput.mClipCoordinate.getX());
                    LogUtils.d("mDynamicNavigateOperate mDynamicNavigateAction: "
                            + wrapper.mDynamicNavigateOutput.mDynamicNavigateAction);
                    int minuteCount = (int) (wrapper.mDynamicNavigateOutput.mRemainingLength / 78);
                    String extra = "";
                    if (minuteCount == 0) {
                        minuteCount = 1;
                        extra = getString(R.string.less_than);
                    }

                    mDynamicInfoText.setText(getString(R.string.remaining)
                            + (int) wrapper.mDynamicNavigateOutput.mRemainingLength + getString(R.string.meter)
                            + " " + extra + minuteCount + getString(R.string.minute));
                }
                if (mHasDrawNavLine || mHasDrawTransientMavLine) {
                    if (wrapper != null && wrapper.mNavigateMapOperate != null) {
                        String mode = "";
                        if (wrapper.mNavigateMapOperate.mMode == DynamicNavigationMode.FOLLOW) {
                            mode = "??";
                        }
                        if (wrapper.mNavigateMapOperate.mMode == DynamicNavigationMode.NORTH) {
                            mode = "??";
                        }
                        LogUtils.d("mNavigateMapOperate:" + mode);
                        double x = wrapper.mNavigateMapOperate.mDirectionX;
                        double y = wrapper.mNavigateMapOperate.mDirectionY;
                        double z = wrapper.mNavigateMapOperate.mDirectionZ;

                        double cx = wrapper.mNavigateMapOperate.mClipCoordinate.getX();
                        double cy = wrapper.mNavigateMapOperate.mClipCoordinate.getY();
                        LogUtils.d("mNavigateMapOperate: direction (" + x + "," + y + "," + z + ")");
                        LogUtils.d("mNavigateMapOperate: coo (" + cx + "," + cy + ")");
                        LogUtils.d(
                                "mNavigateMapOperate=================================================================================================");
                        mMapView.navigateOperate(wrapper.mNavigateMapOperate);
                    }
                }
            }
        });

        mBeaconPositioningManager = new BeaconPositioningManager(MapDetailActivity.this, appKey);
        // ????
        mBeaconPositioningManager
                .setOnLocationChangeListener(new PositioningManager.OnLocationChangeListener<BleLocation>() {
                    @Override
                    public void onLocationChange(PositioningManager.LocationStatus locationStatus,
                            BleLocation bleLocation, BleLocation newLocation) {
                        if (newLocation == null) {
                            LogUtils.d("null onLocationChange:" + locationStatus);
                            return;
                        }
                        switch (locationStatus) {
                        case MOVE:
                            mCurrentBleLocation = newLocation;
                            handleLocationMove(mCurrentBleLocation);
                            break;
                        case START:
                            Coordinate start = newLocation.getPoint().getCoordinate();
                            LogUtils.d("onLocation Start: " + "x = " + start.getX() + ", y =" + " " + start.getY());

                            PositioningUtil.positionLocation(1L, mPositioningLayer, newLocation);
                            break;
                        case STOP:
                            Coordinate stop = newLocation.getPoint().getCoordinate();
                            LogUtils.d("onLocation Stop: " + "x = " + stop.getX() + ", y =" + " " + stop.getY());
                            break;
                        case CLOSE:
                            Coordinate close = newLocation.getPoint().getCoordinate();
                            LogUtils.d("onLocation Close: " + "x = " + close.getX() + ", y =" + " " + close.getY());
                            break;
                        default:
                            break;
                        }
                    }
                });

        //?
        mBeaconPositioningManager.start();
        mLocateOnOff.setSelected(true);
        mDynamicNaviMode.setSelected(true);

        mNavigateManager.setOnNavigateComplete(new NavigateManager.OnNavigateComplete() {
            @Override
            public void onNavigateComplete(NavigateManager.NavigateState navigateState,
                    FeatureCollection featureCollection) {
                hideProgressDialog();
                if (featureCollection == null) {
                    return;
                }
                if (mNavFeatureLayer != null) { //??
                    mNavFeatureLayer.clearFeatures();
                    mNavFeatureLayer.addFeatures(featureCollection);
                    mHasDrawNavLine = true;
                }
                if (mIsFetchingTransientNavData) {
                    mHasDrawNavLine = false;
                    mHasDrawTransientMavLine = true;

                    mTransientMark = createMark("", mCurrentFloorId, mTransientWorldPoint.x, mTransientWorldPoint.y,
                            true, R.drawable.icon_turn_add);
                    mMapView.addOverlay(mTransientMark);
                }

                mNavigationConnectInfo = mNavigateManager.getConnectInfo();
                if (mNavigationConnectInfo != null) {
                    for (ConnectedInfo aNavigationConnectInfo : mNavigationConnectInfo) {

                        double connectWorldX = aNavigationConnectInfo.getCoordinate().getX();
                        double connectWorldY = aNavigationConnectInfo.getCoordinate().getY();
                        long connectFloorId = aNavigationConnectInfo.getFloorId();
                        long connectPoiId = aNavigationConnectInfo.getPoiId();

                        LogUtils.d(connectFloorId + " " + connectPoiId + " " + connectWorldX + " " + connectWorldY);

                        final Mark connectMark = createMark("", connectFloorId, connectWorldX, connectWorldY, true,
                                R.drawable.icon_turn_elevator);

                        mDataSource.requestPOI(connectPoiId,
                                new DataSource.OnRequestDataEventListener<LocationModel>() {
                                    @Override
                                    public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                            LocationModel locationModel) {
                                        if (resourceState != DataSource.ResourceState.ok) {
                                            return;
                                        }
                                        if (locationModel == null) {
                                            return;
                                        }
                                        Param<MapElement> param = new Param<>("category", MapElement.class);
                                        MapElement categoryElement = param.get(locationModel);
                                        long cateId;
                                        if (categoryElement != null) {
                                            cateId = CategoryModel.id.get(categoryElement);
                                        } else {
                                            cateId = 0;
                                        }
                                        if (cateId != 0) {
                                            String cateText = mConnectMap.get(cateId);
                                            if (!TextUtils.isEmpty(cateText)) {
                                                if (cateText.contains("")) {
                                                    connectMark.setIcon(R.drawable.icon_turn_elevator);
                                                }
                                                if (cateText.contains("")) {
                                                    connectMark.setIcon(R.drawable.icon_turn_escalator);
                                                }
                                                if (cateText.contains("")) {
                                                    connectMark.setIcon(R.drawable.icon_turn_stairs);
                                                }
                                                if (cateText.contains("??")) {
                                                    connectMark.setIcon(R.drawable.icon_turn_ramp);
                                                }
                                                if (cateText.contains("") || cateText.contains("?")) {
                                                    connectMark.setIcon(R.drawable.icon_turn_gate);
                                                }
                                                connectMark.setConnectText(cateText);
                                            }
                                        }
                                    }
                                });
                        connectMark.setTitle("");
                        mMapView.addOverlay(connectMark);
                        mConnectMarkList.add(connectMark);
                    }
                }

                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mBtnSelectTransient.setVisibility(View.VISIBLE);
                        mSetStart.setVisibility(View.GONE);
                        mPoiInfoContainer.setVisibility(View.GONE);

                        mDistanceTimeContainer.setVisibility(View.VISIBLE);
                        if (TextUtils.isEmpty(mStartMark.getLocationText())) {
                            mStartLocateText.setText(mStartMark.getFloorText());
                        } else {
                            mStartLocateText.setText(mStartMark.getLocationText());
                        }
                        if (TextUtils.isEmpty(mEndMark.getLocationText())) {
                            mEndLocateText.setText(mEndMark.getFloorText());
                        } else {
                            mEndLocateText.setText(mEndMark.getLocationText());
                        }

                        mClearNavLine.setVisibility(View.GONE);
                        mExpandArrow.setVisibility(View.GONE);
                        mDistanceText.setText(
                                (int) mNavigateManager.getTotalLineLength() + " " + getString(R.string.meter) + "");
                        int minute = (int) (mNavigateManager.getTotalLineLength() / 1.3 / 60);
                        mTimeText.setText((minute == 0 ? 1 : minute) + getString(R.string.minute) + "");
                    }
                });

                LogUtils.d(
                        "Navigate: " + "" + String.valueOf(mNavigateManager.getTotalLineLength()));
                LogUtils.d("Navigate: " + "" + featureCollection.getSize());
                LogUtils.d("Navigate: " + ""
                        + String.valueOf(mNavigateManager.getFloorLineLength(mCurrentFloorId)));
                if (mHasLocated) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mBlueGoThere.setImageResource(R.drawable.btn_foot_navigation);
                            mBlueGoThere.setVisibility(View.VISIBLE);
                        }
                    });
                }
            }
        });

        /**
         * ??,????
         */
        mMapView.setOnChangePlanarGraph(new MapView.OnChangePlanarGraph() {
            @Override
            public void onChangePlanarGraph(PlanarGraph oldPlanarGraph, PlanarGraph newPlanarGraph,
                    long oldPlanarGraphId, long newPlanarGraphId) {
                LogUtils.d("Navigate: " + "oldPlanarGraphId = " + oldPlanarGraphId + "; " + "newPlanarGraphId = "
                        + newPlanarGraphId);
                mCurrentFloorId = newPlanarGraphId;
                mNavFeatureLayer = new FeatureLayer("navigate");
                mMapView.addLayer(mNavFeatureLayer);
                mMapView.setLayerOffset(mNavFeatureLayer);
                if (mNavigateManager != null) {
                    mNavigateManager.switchPlanarGraph(newPlanarGraphId);
                }

                mCompass.invalidate();
                mArchitect.invalidate();

                if (mFloorList == null || mFloorList.size() == 0) {
                    return;
                }

                for (int i = 0; i < mFloorList.size(); i++) {
                    if (LocationModel.id.get(mFloorList.get(i)) == newPlanarGraphId) {
                        mBtnFloor.setText(LocationModel.address.get(mFloorList.get(i)));
                        mFloorAdapter.setCurrent(i);
                        break;
                    }
                }
            }
        });

        if (mDataSource == null) {
            return;
        }
        mDataSource.requestMap(mMapId, new DataSource.OnRequestDataEventListener<MapModel>() {
            @Override
            public void onRequestDataEvent(DataSource.ResourceState resourceState, MapModel mapModel) {
                if (resourceState != DataSource.ResourceState.ok) {
                    hideProgressDialog();
                    ToastUtils.showToast("");
                    return;
                }
                mMapPoi = MapModel.POI.get(mapModel);
                mDataSource.requestPOI(mMapPoi, new DataSource.OnRequestDataEventListener<LocationModel>() {
                    @Override
                    public void onRequestDataEvent(DataSource.ResourceState resourceState,
                            final LocationModel locationModel) {
                        if (resourceState != DataSource.ResourceState.ok) {
                            hideProgressDialog();
                            ToastUtils.showToast(R.string.map_load_fail);
                            return;
                        }

                        mTitle.setText(LocationModel.name.get(locationModel));

                        long id = LocationModel.id.get(locationModel);
                        String type = LocationModel.type.get(locationModel);
                        switch (type) {
                        case LocationModel.PLANARGRAPH://?
                        case LocationModel.FLOOR://
                            mDataSource.requestPlanarGraph(id,
                                    new DataSource.OnRequestDataEventListener<PlanarGraph>() {
                                        @Override
                                        public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                                PlanarGraph planarGraph) {
                                            if (resourceState != DataSource.ResourceState.ok) {
                                                hideProgressDialog();
                                                ToastUtils.showToast(R.string.map_load_fail);
                                                return;
                                            }
                                            hideProgressDialog();
                                            if (planarGraph == null) {
                                                LogUtils.d("planarGraph is null");
                                                return;
                                            }
                                            mMapView.drawPlanarGraph(planarGraph);
                                            afterDrawPlanarGraph();
                                        }
                                    });
                            break;
                        case LocationModel.BUILDING://
                            mDataSource.requestPOIChildren(id,
                                    new DataSource.OnRequestDataEventListener<LocationList>() {
                                        @Override
                                        public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                                LocationList locationList) {
                                            if (resourceState != DataSource.ResourceState.ok) {
                                                ToastUtils.showToast(R.string.map_load_fail);
                                                return;
                                            }

                                            //locationList,?mDeprecatedAdapter.
                                            mDeprecatedAdapter = new DataListAdapter<>(MapDetailActivity.this,
                                                    android.R.layout.simple_spinner_item, locationList,
                                                    Constant.FLOOR_SHOW_FIELD);
                                            mDeprecatedAdapter.setDropDownViewResource(
                                                    android.R.layout.simple_spinner_dropdown_item);

                                            mFloorList = new ArrayList<>();
                                            //?index
                                            int current = 0;

                                            //
                                            if (locationList.getSize() > 0) {
                                                for (int i = 0; i < locationList.getSize(); i++) {
                                                    LocationModel model = locationList.getPOI(i);
                                                    if (model != null) {
                                                        mFloorList.add(model);
                                                        if (FloorModel.default_.get(model)) {
                                                            fetchPlanarGraph(LocationModel.id.get(model), null);
                                                            mBtnFloor.setText(
                                                                    LocationModel.address.get(mFloorList.get(i)));
                                                            current = i;
                                                        }
                                                    }
                                                }
                                            }
                                            int mFloorWidth = DisplayUtils.dp2Px(MapDetailActivity.this, 36);
                                            int mFloorHeight;
                                            if (mFloorList.size() >= 3) {
                                                mFloorHeight = 3 * mFloorWidth + mFloorWidth / 2;
                                            } else {
                                                mFloorHeight = mFloorWidth * mFloorList.size();
                                            }
                                            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mFloorRecyclerView
                                                    .getLayoutParams();
                                            params.width = mFloorWidth;
                                            params.height = mFloorHeight;
                                            mFloorRecyclerView.setLayoutParams(params);
                                            mFloorAdapter = new FloorAdapter(MapDetailActivity.this, mFloorList);
                                            mFloorAdapter.setCurrent(current);
                                            final LinearLayoutManager layoutManager = new LinearLayoutManager(
                                                    MapDetailActivity.this, LinearLayoutManager.VERTICAL, true);
                                            mFloorRecyclerView.setLayoutManager(layoutManager);
                                            mFloorRecyclerView.setAdapter(mFloorAdapter);

                                            mFloorRecyclerView
                                                    .addOnScrollListener(new RecyclerView.OnScrollListener() {
                                                        @Override
                                                        public void onScrolled(RecyclerView recyclerView, int dx,
                                                                int dy) {
                                                            if (dx > 0) {
                                                                mVisibleItemCount = layoutManager.getChildCount();
                                                                mTotalItemCount = layoutManager.getItemCount();
                                                                mPastVisibleItemCount = layoutManager
                                                                        .findFirstVisibleItemPosition();

                                                                if (!isEnd) {
                                                                    if ((mVisibleItemCount
                                                                            + mPastVisibleItemCount) >= mTotalItemCount) {
                                                                        isEnd = true;
                                                                    }
                                                                }
                                                            } else {
                                                                isEnd = false;
                                                            }
                                                        }
                                                    });
                                            mFloorAdapter.setOnItemClickListener(
                                                    new FloorAdapter.OnRecyclerViewItemClickListener() {
                                                        @Override
                                                        public void onItemClick(View view, LocationModel data) {
                                                            for (int i = 0; i < mFloorList.size(); i++) {
                                                                if (LocationModel.id.get(mFloorList.get(i))
                                                                        .longValue() == LocationModel.id.get(data)
                                                                                .longValue()) {
                                                                    mBtnFloor.setText(
                                                                            LocationModel.address.get(data));
                                                                    mFloorAdapter.setCurrent(i);
                                                                    //?floorId?
                                                                    fetchPlanarGraph(LocationModel.id.get(data),
                                                                            getString(R.string.changing_floor));
                                                                    mFloorRecyclerView.setVisibility(View.GONE);
                                                                    break;
                                                                }
                                                            }
                                                        }
                                                    });
                                            hideProgressDialog();
                                        }
                                    });
                            break;
                        default:
                            break;
                        }
                    }
                });
            }
        });
    }

    /**
     * ??.
     *
     * @param newLocation ???.
     */
    private void handleLocationMove(BleLocation newLocation) {
        mLocateFloorId = Location.floorId.get(newLocation.getProperties());

        if (mCurrentFloorId != mLocateFloorId && mLocateFloorId != 0) {
            if (!mHasFetchInitFloor) {
                fetchPlanarGraphForLocate(mLocateFloorId, getString(R.string.changing_floor));
            }
        }

        Coordinate move = newLocation.getPoint().getCoordinate();
        LogUtils.d("onLocation Move: " + "x = " + move.getX() + ", y =" + " " + move.getY());
        PositioningUtil.positionLocation(1L, mPositioningLayer, newLocation);
        mNavigateManager.dynamicNavigate(newLocation.getPoint().getCoordinate(), mLocateFloorId, 0);
        // ???
        mHasLocated = true;
    }

    /**
     * ?
     */
    private void fetchPlanarGraph(final long id, String info) {
        if (mCurrentFloorId == id || id == 0) {
            return;
        }
        if (TextUtils.isEmpty(info)) {
            showProgressDialog();
        } else {
            showProgressDialog(info);
        }
        if (mDataSource == null) {
            return;
        }
        mDataSource.requestPlanarGraph(id, new DataSource.OnRequestDataEventListener<PlanarGraph>() {
            @Override
            public void onRequestDataEvent(DataSource.ResourceState state, PlanarGraph planarGraph) {
                hideProgressDialog();
                if (state != DataSource.ResourceState.ok) {
                    ToastUtils.showToast(mHandler, R.string.map_load_fail);
                    return;
                }
                if (planarGraph == null) {
                    return;
                }
                mMapView.drawPlanarGraph(planarGraph);
                afterDrawPlanarGraph();
                mCurrentFloorId = id;
            }
        });
    }

    /**
     * ?????.
     */
    private boolean mIsFetchingFloorForLocate = false;

    /**
     * ??,????.
     */
    private boolean mHasFetchInitFloor = false;

    /**
     * ?(?)
     */
    private void fetchPlanarGraphForLocate(final long id, String info) {
        if (mIsFetchingFloorForLocate) {
            return;
        }
        if (mCurrentFloorId == id || id == 0) {
            return;
        }
        if (TextUtils.isEmpty(info)) {
            showProgressDialog();
        } else {
            showProgressDialog(info);
        }
        if (mDataSource == null) {
            return;
        }
        mIsFetchingFloorForLocate = true;
        mDataSource.requestPlanarGraph(id, new DataSource.OnRequestDataEventListener<PlanarGraph>() {
            @Override
            public void onRequestDataEvent(DataSource.ResourceState state, PlanarGraph planarGraph) {
                hideProgressDialog();
                if (state != DataSource.ResourceState.ok) {
                    ToastUtils.showToast(mHandler, R.string.map_load_fail);
                    return;
                }
                if (planarGraph == null) {
                    return;
                }
                mMapView.drawPlanarGraph(planarGraph);
                afterDrawPlanarGraph();
                mCurrentFloorId = id;
                mIsFetchingFloorForLocate = false;
                mHasFetchInitFloor = true;
            }
        });
    }

    /**
     * ?
     */
    private void fetchPlanarGraph(final long id, final SearchResultEvent event, String info) {
        if (mDataSource == null) {
            return;
        }
        if (mCurrentFloorId == id || id == 0) {
            return;
        }
        if (TextUtils.isEmpty(info)) {
            showProgressDialog();
        } else {
            showProgressDialog(info);
        }
        mDataSource.requestPlanarGraph(id, new DataSource.OnRequestDataEventListener<PlanarGraph>() {
            @Override
            public void onRequestDataEvent(DataSource.ResourceState state, PlanarGraph planarGraph) {
                hideProgressDialog();
                if (state != DataSource.ResourceState.ok) {
                    ToastUtils.showToast(mHandler, R.string.map_load_fail);
                    return;
                }
                if (planarGraph == null) {
                    return;
                }
                mMapView.drawPlanarGraph(planarGraph);
                afterDrawPlanarGraph();

                mCurrentFloorId = id;

                Feature feature = mMapView.selectFeature(event.mPOIId);

                long cate;
                cate = LocationModel.category.get(feature);

                selectedFeature = mMapView.selectFeature(LocationModel.id.get(event.mList.get(0)));
                if (selectedFeature != null) {
                    Types.Point screenPoint = mMapView.converToScreenCoordinate(selectedFeature.getCentroid().x,
                            selectedFeature.getCentroid().y);

                    mGoTherePixelX = screenPoint.x;
                    mGoTherePixelY = screenPoint.y;
                }
                //?
                mBtnFloor.setText(event.mFloorName);
                mFloorAdapter.setCurrent(event.mFloorIndex);
                showBottomContainer();
                mPoiInfoContainer.setVisibility(View.VISIBLE);
                mBlueGoThere.setVisibility(View.VISIBLE);
                if (!TextUtils.isEmpty(event.mPOIDisplayText)) {
                    mPoiNameText.setText(event.mPOIDisplayText);
                }

                if (!TextUtils.isEmpty(event.mPOICategoryText)) {
                    mCategoryText.setText(event.mPOICategoryText);
                } else if (cate != 0) {
                    mDataSource.requestCategory(cate, new DataSource.OnRequestDataEventListener<CategoryModel>() {
                        @Override
                        public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                CategoryModel categoryModel) {
                            if (categoryModel == null) {
                                return;
                            }
                            mCategoryText.setText(CategoryModel.NAME3.get(categoryModel));
                        }
                    });
                }
                if (selectedFeature != null) {
                    mEndMark = createMark("", mCurrentFloorId, selectedFeature.getCentroid().x,
                            selectedFeature.getCentroid().y, true, R.drawable.icon_marker);
                    mMapView.addOverlay(mEndMark);
                }
            }
        });
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
        /**
         * zoomIn
         */
        case R.id.zoom_in:
            mMapView.zoomIn();
            mArchitect.invalidate();
            break;
        /**
         * zoomOut
         */
        case R.id.zoom_out:
            mMapView.zoomOut();
            mArchitect.invalidate();
            break;
        /**
         * ,??.
         */
        case R.id.compass:
            Types.Point center = new Types.Point(DisplayUtils.getScreenWidthPixel(MapDetailActivity.this) / 2,
                    DisplayUtils.getScreenHeightPixel(MapDetailActivity.this) / 2);
            double angle = mMapView.getRotate();
            mMapView.rotate(center, -angle);
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mCompass.invalidate();
                }
            }, 100);
            break;
        /**
         * ??
         */
        case R.id.title_icon_right:
            if (mMapView.checkInitializing()) {
                return;
            }
            //??overlay,.
            mMapView.removeAllOverlay();
            if (mNavigateManager != null) {
                mNavigateManager.clear();
            }
            if (mNavFeatureLayer != null) {
                mNavFeatureLayer.clearFeatures();
            }
            mStartMark = null;
            mEndMark = null;
            mTransientMark = null;

            mThroughContainer.setVisibility(View.GONE);
            mBtnSelectTransient.setVisibility(View.GONE);

            mDistanceText.setText("");
            mTimeText.setText("");
            mStartLocateText.setText("");
            mEndLocateText.setText("");
            mDistanceTimeContainer.setVisibility(View.GONE);

            mBlueGoThere.setVisibility(View.VISIBLE);
            mClearNavLine.setVisibility(View.GONE);
            mSetStart.setVisibility(View.GONE);

            hideBottomContainer();

            mMarkList.clear();
            List<LocationWrapper> list = new ArrayList<>();
            if (mFloorList != null) {
                for (LocationModel model : mFloorList) {
                    LocationWrapper wrapper = new LocationWrapper();
                    wrapper.id = LocationModel.id.get(model);
                    wrapper.name = LocationModel.address.get(model);
                    list.add(wrapper);
                }
            }
            Bundler.searchActivity(SearchActivity.SearchType.POI, null, null, mMapPoi, mCurrentFloorId)
                    .mFloor((ArrayList<LocationWrapper>) list).start(MapDetailActivity.this);
            break;

        /**
         * POI?
         */
        case R.id.expand_arrow:
            FeatureWrapper wrapper = new FeatureWrapper();
            Param<MapElement> openTimeParam = new Param<>("opening_time", MapElement.class);
            Param<MapElement> websiteParam = new Param<>("website", MapElement.class);
            Param<MapElement> phoneParam = new Param<>("phone", MapElement.class);
            if (mNearByPoi != null) {
                wrapper.name = LocationModel.name.get(mNearByPoi);
                wrapper.location = LocationModel.address.get(mNearByPoi);
                wrapper.time = openTimeParam.get(mNearByPoi).getString();
                wrapper.phone = phoneParam.get(mNearByPoi).getString();
                wrapper.website = websiteParam.get(mNearByPoi).getString();
                wrapper.category = LocationModel.category
                        .get(mMapView.selectFeature(LocationModel.id.get(mNearByPoi)));
            }
            if (selectedFeature != null) {
                wrapper.name = mPoiNameText.getText().toString();
                wrapper.location = LocationModel.address.get(selectedFeature);
                wrapper.time = openTimeParam.get(selectedFeature).getString();
                wrapper.phone = phoneParam.get(selectedFeature).getString();
                wrapper.website = websiteParam.get(selectedFeature).getString();
                long cate = LocationModel.category.get(selectedFeature);
                if (cate != 0) {
                    wrapper.category = cate;
                }
            }

            Bundler.pOIDetailActivity(wrapper).start(MapDetailActivity.this);
            break;

        /**
         * ?
         */
        case R.id.btn_floor:
            if (mFloorRecyclerView.getVisibility() == View.VISIBLE) {
                mFloorRecyclerView.setVisibility(View.GONE);
            } else if (mFloorRecyclerView.getVisibility() == View.GONE) {
                mFloorRecyclerView.setVisibility(View.VISIBLE);
                LinearLayoutManager mLayoutManager = (LinearLayoutManager) mFloorRecyclerView.getLayoutManager();
                mLayoutManager.scrollToPositionWithOffset(0, 0);
            }
            break;

        /**
         * ?,/?
         */
        case R.id.blue_circle:
            //?
            if (mBlueGoThere.getDrawable().getConstantState() == getResources()
                    .getDrawable(R.drawable.btn_foot_navigation).getConstantState()) {
                //?.
                getIntoDynamicNavi();
                mDynamicNavigateAdapter.setData(Arrays.asList(mNavigateManager.getStepInfo(mCurrentFloorId)));
                //                    int xxxx = mNavigateManager.getAllStepInfo().size();
                //                    ToastUtils.showToast(xxxx + " ");
                mDynamicNavigateParams = new DynamicNavigateParams();
                mDynamicNavigateParams.mDynamicNavigationMode = DynamicNavigationMode.FOLLOW;
                mDynamicNavigateParams.mFloorId = mLocateFloorId;
                mDynamicNavigateParams.mJudgeArriveLength = 1;
                mDynamicNavigateParams.mLineMode = LineMode.CHANGE_COLOR;
                mNavigateManager.initParams(mDynamicNavigateParams);
                mNavigateManager.start(new Coordinate(0, 0), mLocateFloorId, 0);
            }
            //
            if (mBlueGoThere.getDrawable().getConstantState() == getResources()
                    .getDrawable(R.drawable.btn_navigation).getConstantState()) {
                if (mHasLocated) {
                    Coordinate startCoo = null;
                    if (mCurrentBleLocation != null) {
                        startCoo = mCurrentBleLocation.getPoint().getCoordinate();
                    }
                    if (startCoo != null) {
                        showProgressDialog();
                        mNavigateManager.navigation(startCoo, mLocateFloorId, mEndMark.getCoo(),
                                mEndMark.getFloorId(), new Coordinate[] {}, new long[] {});
                    }
                    break;
                }
                mMapView.removeAllOverlay();
                Types.Point point = mMapView.converToWorldCoordinate(mGoTherePixelX, mGoTherePixelY);
                mEndMark = createMark("", mCurrentFloorId, point.x, point.y, true, R.drawable.icon_end);
                mEndMark.setFloorText(mBtnFloor.getText().toString());
                mEndMark.setLocationText(mPoiNameText.getText().toString());
                String name = "";
                if (selectedFeature != null) {
                    name = LocationModel.name.get(selectedFeature);
                }
                if (TextUtils.isEmpty(name)) {
                    name = mPoiNameText.getText().toString();
                }
                mEndMark.setLocationText(name);
                mMapView.addOverlay(mEndMark);
                mBlueGoThere.setVisibility(View.GONE);
                mPoiInfoContainer.setVisibility(View.GONE);
                mSelectText.setVisibility(View.VISIBLE);
                break;
            }

            /**
             * ,
             */
        case R.id.set_start:
            mStartMark.setIcon(R.drawable.icon_start);
            mStartMark.setFloorText(mBtnFloor.getText().toString());
            mStartMark.setLocationText(mPoiNameText.getText().toString());
            //
            showProgressDialog();
            mNavigateManager.navigation(mStartMark.getWorldX(), mStartMark.getWorldY(), mStartMark.getFloorId(),
                    mEndMark.getWorldX(), mEndMark.getWorldY(), mEndMark.getFloorId());
            break;

        /**
         * 
         */
        case R.id.clear_nav_line:
            if (mNavFeatureLayer != null) {
                mNavFeatureLayer.clearFeatures();
            }
            mIsFetchingTransientNavData = false;
            mBtnSelectTransient.setVisibility(View.GONE);
            mCanSelectPoint = false;
            mHasDrawNavLine = false;
            mHasDrawTransientMavLine = false;
            hideBottomContainer();
            mClearNavLine.setVisibility(View.GONE);
            mPoiInfoContainer.setVisibility(View.VISIBLE);
            mBlueGoThere.setVisibility(View.GONE);
            mMapView.removeAllOverlay();

            mStartMark = null;
            mEndMark = null;
            mTransientMark = null;
            mGoTherePixelX = 0;
            mGoTherePixelY = 0;
            selectedFeature = null;
            break;
        /**
         * ??
         */
        case R.id.locate:
            if (mLocateOnOff.isSelected()) {
                mBeaconPositioningManager.stop();
                mLocateOnOff.setSelected(false);
            } else {
                if (mMapView.checkInitializing()) {
                    return;
                }
                mBeaconPositioningManager.start(); // ?
                mLocateOnOff.setSelected(true);
            }
            break;
        /**
         * ??
         */
        case R.id.btn_select_transient:
            if (mBtnSelectTransient.isSelected()) {
                mThroughContainer.setVisibility(View.GONE);
                mBtnSelectTransient.setSelected(false);
            } else {
                mThroughContainer.setVisibility(View.VISIBLE);
                mBtnSelectTransient.setSelected(true);
            }
            break;

        /**
         * 
         */
        case R.id.transient_clear_container:
            for (Mark mark : mMarkList) {
                mMapView.removeOverlay(mark);
            }
            mThroughContainer.setVisibility(View.GONE);
            mBtnSelectTransient.setSelected(false);
            mMapView.removeOverlay(mTransientMark);
            mTransientMark = null;
            mCanSelectPoint = false;
            mIsFetchingTransientNavData = false;
            if (mHasDrawTransientMavLine) {
                if (mNavFeatureLayer != null) {
                    mNavFeatureLayer.clearFeatures();
                }
                //?????
                mNavigateManager.navigation(mStartMark.getWorldX(), mStartMark.getWorldY(), mStartMark.getFloorId(),
                        mEndMark.getWorldX(), mEndMark.getWorldY(), mEndMark.getFloorId());
            }
            break;
        /**
         * ?
         */
        case R.id.transient_add_bath:
            mThroughContainer.setVisibility(View.GONE);
            mBtnSelectTransient.setSelected(false);
            if (mHasShowAllBath) {
                return;
            }
            if (mHasDrawNavLine || mHasDrawTransientMavLine) {
                if (mDataSource == null) {
                    return;
                }
                mDataSource.search(null, 0, 10, new long[] { mCurrentFloorId },
                        new long[] { 23024000, 23025000, 23059000, 23063000 },
                        new DataSource.OnRequestDataEventListener<LocationPagingList>() {
                            @Override
                            public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                    LocationPagingList locationPagingList) {
                                if (resourceState != DataSource.ResourceState.ok) {
                                    return;
                                }
                                if (locationPagingList.getSize() == 0) {
                                    ToastUtils.showToast(getString(R.string.no_facility));
                                    return;
                                }
                                for (int i = 0; i < locationPagingList.getSize(); i++) {
                                    LocationModel model = locationPagingList.getPOI(i);
                                    long id = LocationModel.id.get(model);
                                    Feature feature = mMapView.selectFeature(id);
                                    if (feature != null) {
                                        Mark mark = createMarkWithTag("", mCurrentFloorId,
                                                feature.getCentroid().getX(), feature.getCentroid().getY(), true, 0,
                                                id);
                                        mMapView.addOverlay(mark);
                                        mMarkList.add(mark);

                                        mark.setOnClickListener(mTransientBathAtmListener);
                                    }
                                }
                                mHasShowAllBath = true;
                            }
                        });
            }
            break;
        /**
         * ?atm
         */
        case R.id.transient_add_atm:
            mThroughContainer.setVisibility(View.GONE);
            mBtnSelectTransient.setSelected(false);
            if (mHasShowAllAtm) {
                return;
            }
            if (mHasDrawNavLine || mHasDrawTransientMavLine) {
                if (mDataSource == null) {
                    return;
                }
                mDataSource.search(null, 0, 10, new long[] { mCurrentFloorId }, new long[] { 24112000 },
                        new DataSource.OnRequestDataEventListener<LocationPagingList>() {
                            @Override
                            public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                    LocationPagingList locationPagingList) {
                                if (resourceState != DataSource.ResourceState.ok) {
                                    return;
                                }
                                if (locationPagingList.getSize() == 0) {
                                    ToastUtils.showToast(getString(R.string.no_facility));
                                    return;
                                }
                                for (int i = 0; i < locationPagingList.getSize(); i++) {
                                    LocationModel model = locationPagingList.getPOI(i);
                                    long id = LocationModel.id.get(model);
                                    Feature feature = mMapView.selectFeature(id);
                                    if (feature != null) {
                                        Mark mark = createMark("", mCurrentFloorId, feature.getCentroid().getX(),
                                                feature.getCentroid().getY(), true, R.drawable.icon_marker);
                                        mMapView.addOverlay(mark);
                                        mMarkList.add(mark);

                                        mark.setTag(id);
                                        mark.setOnClickListener(mTransientBathAtmListener);
                                    }
                                }
                                mHasShowAllAtm = true;
                            }
                        });
            }
            break;
        /**
         * ??
         */
        case R.id.transient_container:
            mThroughContainer.setVisibility(View.GONE);
            mBtnSelectTransient.setSelected(false);
            if (mHasDrawNavLine) {
                mCanSelectPoint = true;
            }
            break;
        case R.id.base_bottom_container:
            break;
        case R.id.bottom_info_container:
            break;
        /**
         * ?.
         */
        case R.id.iv_close_navi:
        case R.id.quit_navi:
            CommonDialog pickPhoneDialog = new CommonDialog(MapDetailActivity.this,
                    new CommonDialog.onConfirmListener() {
                        @Override
                        public void onConfirm() {
                            if (mNavigateManager != null) {
                                mNavigateManager.stop();
                                mNavigateManager.clear();
                            }
                            mLocateOnOff.setVisibility(View.VISIBLE);
                            mDynamicNaviMode.setVisibility(View.INVISIBLE);
                            mCompass.setVisibility(View.VISIBLE);
                            mDynamicContainer.setVisibility(View.GONE);
                            mQuitNaviContainer.setVisibility(View.INVISIBLE);
                            mBtnSelectTransient.setVisibility(View.VISIBLE);
                            mZoomContainer.setVisibility(View.VISIBLE);
                            showBottomContainer();
                            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mLocateOnOff
                                    .getLayoutParams();
                            int bMargin = params.bottomMargin;
                            bMargin -= mQuitNaviContainer.getHeight();
                            params.bottomMargin = bMargin;
                            mLocateOnOff.setLayoutParams(params);
                        }
                    });
            pickPhoneDialog.setConfirmText(getResources().getString(R.string.confirm));
            @SuppressLint("InflateParams")
            TextView tv = (TextView) LayoutInflater.from(MapDetailActivity.this).inflate(R.layout.dialog_text_view,
                    null);
            tv.setText(getString(R.string.confirm_quit_dynamic_navigate));
            pickPhoneDialog.setView(tv);
            pickPhoneDialog.show();
            break;
        /**
         * ??.
         */
        case R.id.dynamic_mode:
            if (mDynamicNaviMode.isSelected()) {
                mDynamicNaviMode.setSelected(false);
                mNavigateManager.setNavigateMode(DynamicNavigationMode.NORTH);
            } else {
                mDynamicNaviMode.setSelected(true);
                mNavigateManager.setNavigateMode(DynamicNavigationMode.FOLLOW);
            }
            break;

        default:
            break;
        }
    }

    /**
     * ??view?.
     */
    public void getIntoDynamicNavi() {
        mCompass.setVisibility(View.GONE);
        mZoomContainer.setVisibility(View.GONE);
        mBtnSelectTransient.setVisibility(View.GONE);
        mDynamicNaviMode.setVisibility(View.VISIBLE);
        mLocateOnOff.setVisibility(View.INVISIBLE);
        mDynamicContainer.setVisibility(View.VISIBLE);
        mQuitNaviContainer.setVisibility(View.VISIBLE);
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mLocateOnOff.getLayoutParams();
        int bMargin = params.bottomMargin;
        bMargin += mQuitNaviContainer.getHeight();
        params.bottomMargin = bMargin;
        mLocateOnOff.setLayoutParams(params);
        hideBottomContainer();
    }

    /**
     * ??ATM.
     */
    private View.OnClickListener mTransientBathAtmListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //??  ???
            long id = (long) view.getTag();
            Feature transientFeature = mMapView.selectFeature(id);
            if (mHasDrawTransientMavLine || mHasDrawNavLine) {
                mIsFetchingTransientNavData = true;
                mHasDrawNavLine = false;
                if (mTransientMark != null) {
                    mMapView.removeOverlay(mTransientMark);
                    mTransientMark = null;
                }
                if (mTransientWorldPoint == null) {
                    mTransientWorldPoint = new Types.Point(transientFeature.getCentroid().x,
                            transientFeature.getCentroid().y);
                } else {
                    mTransientWorldPoint.x = transientFeature.getCentroid().x;
                    mTransientWorldPoint.y = transientFeature.getCentroid().y;
                }
                Coordinate[] coordinates = new Coordinate[] {
                        new Coordinate(mTransientWorldPoint.x, mTransientWorldPoint.y) };
                //??
                mNavigateManager.navigation(mStartMark.getCoo(), mStartMark.getFloorId(), mEndMark.getCoo(),
                        mEndMark.getFloorId(), coordinates, new long[] { mCurrentFloorId });
            }
            for (Mark mark : mMarkList) {
                mMapView.removeOverlay(mark);
            }
            mMarkList.clear();
            mMapView.getOverlayController().refresh();
            mHasShowAllAtm = false;
        }
    };

    /**
     * ??
     */
    @Subscribe
    public void onEvent(final SearchResultEvent event) {
        if (event == null || event.mList == null || event.mList.size() == 0) {
            return;
        }
        mMapView.removeAllOverlay();
        if (event.isSearchPoiByKeyWord) {
            long floorId = LocationModel.id.get(mFloorList.get(event.mFloorIndex));
            if (mCurrentFloorId != floorId) { //??
                fetchPlanarGraph(floorId, event, getString(R.string.changing_floor));
            } else { //?
                selectedFeature = mMapView.selectFeature(event.mPOIId);

                long cate = 0;
                if (selectedFeature != null) {
                    cate = LocationModel.category.get(selectedFeature);
                    Types.Point screenPoint = mMapView.converToScreenCoordinate(selectedFeature.getCentroid().x,
                            selectedFeature.getCentroid().y);
                    mGoTherePixelX = screenPoint.x;
                    mGoTherePixelY = screenPoint.y;
                }
                showBottomContainer();
                mPoiInfoContainer.setVisibility(View.VISIBLE);
                mBlueGoThere.setVisibility(View.VISIBLE);
                if (!TextUtils.isEmpty(event.mPOIDisplayText)) {
                    mPoiNameText.setText(event.mPOIDisplayText);
                } else {
                    mPoiNameText.setText("");
                }

                if (!TextUtils.isEmpty(event.mPOICategoryText)) {
                    mCategoryText.setText(event.mPOICategoryText);
                } else if (cate != 0) {
                    mDataSource.requestCategory(cate, new DataSource.OnRequestDataEventListener<CategoryModel>() {
                        @Override
                        public void onRequestDataEvent(DataSource.ResourceState resourceState,
                                CategoryModel categoryModel) {
                            if (categoryModel == null) {
                                return;
                            }
                            mCategoryText.setText(CategoryModel.NAME3.get(categoryModel));
                            if (TextUtils.isEmpty(mPoiNameText.getText().toString())) {
                                mPoiNameText.setText(CategoryModel.NAME3.get(categoryModel));
                            }
                        }
                    });
                }
                if (selectedFeature != null) {
                    mEndMark = createMark("", mCurrentFloorId, selectedFeature.getCentroid().x,
                            selectedFeature.getCentroid().y, true, R.drawable.icon_marker);
                    mMapView.addOverlay(mEndMark);
                }
            }
            return;
        }

        for (int i = 0; i < event.mList.size(); i++) {
            LocationModel model = event.mList.get(i);
            long id = LocationModel.id.get(model);
            Feature feature = mMapView.selectFeature(id);

            if (feature != null) {
                Mark mark = createMarkWithTag("" + i, 0, feature.getCentroid().getX(), feature.getCentroid().getY(),
                        true, 0, id);

                mark.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //mark?
                        long id = (long) view.getTag();
                        selectedFeature = mMapView.selectFeature(id);
                        Types.Point screenPoint = mMapView.converToScreenCoordinate(selectedFeature.getCentroid().x,
                                selectedFeature.getCentroid().y);

                        mGoTherePixelX = screenPoint.x;
                        mGoTherePixelY = screenPoint.y;

                        mBlueGoThere.setVisibility(View.VISIBLE);
                        showBottomContainer();

                        showSelectedPoiInfo(selectedFeature, mGoTherePixelX, mGoTherePixelY);
                    }
                });

                mMapView.addOverlay(mark);
                mMarkList.add(mark);
            }
        }
    }

    /**
     * tagMark
     *
     * @param title          mark?
     * @param floorId        markid
     * @param worldX         markx??
     * @param worldY         marky??
     * @param showIcon       ?icon
     * @param iconDrawableId icon
     * @param tag            marktag
     * @return ?mark
     */
    private Mark createMarkWithTag(String title, long floorId, double worldX, double worldY, boolean showIcon,
            int iconDrawableId, long tag) {
        Mark mark = new Mark(mMapView.getContext());
        mark.setTitle(title);
        if (floorId != 0) {
            mark.setFloorId(floorId);
        }
        mark.init(new double[] { worldX, worldY });
        if (showIcon) {
            if (iconDrawableId != 0) {
                mark.setIcon(iconDrawableId);
            }
            mark.showIcon();
        } else {
            mark.hideIcon();
        }
        mark.setTag(tag);

        return mark;
    }

    /**
     * mark
     *
     * @param title          mark?
     * @param floorId        markid
     * @param worldX         markx??
     * @param worldY         marky??
     * @param showIcon       ?icon
     * @param iconDrawableId icon
     * @return ?mark
     */
    private Mark createMark(String title, long floorId, double worldX, double worldY, boolean showIcon,
            int iconDrawableId) {
        Mark mark = new Mark(mMapView.getContext());
        mark.setTitle(title);
        if (floorId != 0) {
            mark.setFloorId(floorId);
        }
        mark.init(new double[] { worldX, worldY });
        if (showIcon) {
            if (iconDrawableId != 0) {
                mark.setIcon(iconDrawableId);
            }
            mark.showIcon();
        } else {
            mark.hideIcon();
        }
        return mark;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMapView != null) {
            mMapView.drop();
        }
        if (mNavigateManager != null) {
            mNavigateManager.stop();
            mNavigateManager.drop(); //??
        }
        if (mBeaconPositioningManager != null) {
            mBeaconPositioningManager.stop();
            mBeaconPositioningManager.close();
            mBeaconPositioningManager.drop(); //????
        }
        EventBus.getDefault().unregister(this);
    }

    /**
     * ???
     */
    @SuppressLint("UseSparseArrays")
    private void initConnectCate() {
        mConnectMap = new HashMap<>();
        String[] connectArray = getResources().getStringArray(R.array.connect);
        for (String aZipArray : connectArray) {
            String[] pair = aZipArray.split("-");
            mConnectMap.put(Long.valueOf(pair[0]), pair[1]);
        }
    }
}