package com.example.move;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Toast;

import com.kongqw.rockerlibrary.view.RockerView;
import com.rabtman.wsmanager.WsManager;
import com.rabtman.wsmanager.listener.WsStatusListener;
import com.tencent.map.geolocation.TencentLocation;
import com.tencent.map.geolocation.TencentLocationListener;
import com.tencent.map.geolocation.TencentLocationManager;
import com.tencent.map.geolocation.TencentLocationRequest;
import com.tencent.mapsdk.raster.model.BitmapDescriptorFactory;
import com.tencent.mapsdk.raster.model.LatLng;
import com.tencent.mapsdk.raster.model.Marker;
import com.tencent.mapsdk.raster.model.MarkerOptions;
import com.tencent.tencentmap.mapsdk.map.MapView;
import com.tencent.tencentmap.mapsdk.map.TencentMap;
import com.tencent.tencentmap.mapsdk.map.UiSettings;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Response;
import okio.ByteString;


public class MainActivity extends AppCompatActivity implements TencentLocationListener {
    private double pi = 3.1415926535897932384626;
    public double a = 6378245.0;
    public double ee = 0.00669342162296594323;
    private float clickButtonAlpha = 0.8f;
    private float unClickButtonAlpha = 0.3f;
    private float clickHeadAlpha = 1.0f;
    private float unclickHeadAlpha = 0.3f;
    // 一次搜索,腾讯返回结果经纬度的跨度
    private double latSpan =  0.01369;
    private double lonSpan = 0.01786;
    private DisplayMetrics metrics;
    // 腾讯地图
    MapView mapView = null;
    TencentMap tencentMap = null;
    private Marker marker;
    private boolean isMarker = false;
    private boolean firstLocation = true;
    // 腾讯定位
    TencentLocationManager tencentLocationManager;
    TencentLocationRequest tencentLocationRequest;
    private String appid = "wx19376645db21af08";
    private String openid = "";
    private String gwgo_token = "";

    private Random random;
    // 模拟定位
    private LocationManager locationManager;
    // 持续模拟设置定位线程
    private Thread thread;
    // 设置移动还是停下
    private int isRun = 0;
    private int isPatrol = 0;
    private double patrolSpeed = 0.00000005;
    // 记录当前设置的定位值
    private double longtitude = 0;
    private double latitude = 0;
    // 设置的当前定位海拔
    private double altitude;
    // 设置的当前定位精度
    private float accuracy;
    // 当前行走方向
    private int direct = 0;
    // 基础移动速度
    private double baseSpeed = 0.0000002;
    // 移动速度
    private double speed = 0.0000002;
    // 控制器上的功能组件
    private SeekBar speedSeekBar;
    private Button stopButton;
    private Button backButton;
    private Button filterButton;
    private Button mapButton;
    private Button nextButton;
    private Button patrolButton;
    // 定位范围
    private Button autoButton;
    private int autoCount = 0;
    // 判断控制器是收起还是展开
    private int isBack = 0;
    private RockerView rockerView;
    private double angle = 0;
    private int count = 1;
    private int loop = 10000;
    private int step = 5000;
    // 悬浮窗地图
    private View floatMapView;
    private WindowManager.LayoutParams floatMapViewParams;
    private Button floatMapCloseButton;
    private MapView floatTencentMapView;
    private TencentMap floatTencentMap;

    // 悬浮效果控制器
    private WindowManager windowManager;
    private WindowManager.LayoutParams controllerLayoutParams;
    // 控制器页面
    private View controllerView;
    // 筛选器页面
    private View filterView;
    private WindowManager.LayoutParams filterLayoutParams;
    private LinearLayout headLinearLayout;
    private LayoutParams headLayoutParams;
    // 存储妖灵头像图片
    private String[] headImages;
    // 用于获取assets目录下的图片
    private AssetManager assetManager;
    // 筛选器中选中的妖灵
    private Map<Integer, Bitmap> headBitmaps = new HashMap<>();
    private Set<Integer> allPetSet = new LinkedHashSet<>();
    private Set<Integer> selectedPetSet = new HashSet<>();
    private Set<String> petSet;
    private String drums;
    private List<Double> drumLocations = new ArrayList<>();
    private int drumIndex = 0;
    private String battlefields;
    private List<Double> battlefieldLocations = new ArrayList<>();
    private int battlefieldIndex = 0;
    private String stones;
    private List<Double> stoneLocations = new ArrayList<>();
    private int stoneIndex = 0;
    private SharedPreferences petSharedPreferences;
    private SharedPreferences.Editor editor;
    // 腾讯提供的获取坐标位置附近妖灵的websocket
    private String wssHost = "wss://publicld.gwgo.qq.com?account_value=0&account_type=1&appid=0&token=0";
    // websocket管理,引用的第三方库
    private WsManager wsManager;
    // 用于向websocket发送数据
    private JSONObject jsonObject;
    // 记录websocket返回的妖灵列表
    private JSONArray jsonArray;
    private JSONArray petJsonArray = new JSONArray();
    // 记录当前查找到jsonArray中的哪个妖灵
    private int currentIndex = 0;
    // 每次请求都有requestId,而成功返回时,同样有此Id,通过记录和比较requestId来判断,上次请求是否成功
    private long requestId;
    private boolean requestSuccess = false;
    private long checkRequestId;
    private Toast toast;
    // 触摸板
    private Button saveButton;
    private EditText openidText;
    private EditText tokenText;
    private int saveStatus = 1;
    // 模式
    private int modType = 0;
    private Button modButton;
    // 线程池
    private ExecutorService fixedThreadPool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        saveButton = this.findViewById(R.id.saveButton);
        openidText = this.findViewById(R.id.openidText);
        openidText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                openid = openidText.getText().toString();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
        tokenText = this.findViewById(R.id.tokenText);
        tokenText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                gwgo_token = tokenText.getText().toString();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        init(savedInstanceState);
        continueLocation2();
        showController();
    }

    private void init(Bundle savedInstanceState) {
        initPermission();
        // 初始化妖灵数据
        initPets();
        // 初始化各个控制窗口
        initWindowManager(savedInstanceState);
        initWebsocket();
        initMoveManager();
        initLocation();
        getToken();
    }

    private void initWindowManager(Bundle savedInstanceState) {
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        metrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(metrics);

        // 以下为取其它activity内容
        LayoutInflater layoutInflater = LayoutInflater.from(this);
        // 控制按钮悬浮窗
        controllerView = layoutInflater.inflate(R.layout.activity_controller, null);
        initController();
        // 筛选悬浮窗
        filterView = layoutInflater.inflate(R.layout.activity_filter, null);
        initFilter();
        showPets();
        // 地图悬浮窗
        floatMapView = layoutInflater.inflate(R.layout.activity_map, null);
        initMap(savedInstanceState);
    }

    private void initPermission() {
        // 定位权限
        // 模拟定位权限
        // 悬浮窗权限
        // 三种权限都是必须权限
    }

    // 初始化腾讯地图的一些信息
    private void initMap(Bundle savedInstanceState) {
        mapView = (MapView) floatMapView.findViewById(R.id.floatmapview);
        mapView.onCreate(savedInstanceState);
        tencentMap = mapView.getMap();
        tencentMap.setZoom(15);
        UiSettings uiSettings = mapView.getUiSettings();
        // 地图缩放
        // uiSettings.setZoomGesturesEnabled(false);
        // 地图滚动
        // uiSettings.setScrollGesturesEnabled(false);
        // 当前位置marker

        // 设置点击地图事件监听
        tencentMap.setOnMapClickListener(new TencentMap.OnMapClickListener() {
            @Override
            public void onMapClick(final LatLng latLng) {
                if (modType == 0) {
                    getPets(latLng.getLatitude(), latLng.getLongitude());
                } else {
                    handleMapClick(latLng.getLatitude(), latLng.getLongitude());
                }
            }
        });
        // 设置点击marker的事件监听
        tencentMap.setOnMarkerClickListener(new TencentMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                LatLng pos =  marker.getPosition();
                handleMapClick(pos.getLatitude(), pos.getLongitude());
                return false;
            }
        });
    }

    // 处理点击地图事件
    private void handleMapClick(final double lat, final double lon) {
        moveTo(lat, lon);
    }

    // 初始化腾讯定位的一些信息
    private void initLocation() {
        tencentLocationManager = TencentLocationManager.getInstance(this);
        tencentLocationManager.setCoordinateType(TencentLocationManager.COORDINATE_TYPE_WGS84);
        tencentLocationRequest = TencentLocationRequest.create();
        tencentLocationRequest.setInterval(100);
        tencentLocationManager.requestLocationUpdates(tencentLocationRequest, this);
    }

    // 初始化模拟定位的一些信息
    private void initMoveManager() {
        if (Build.VERSION.SDK_INT < 23) {
            if (Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
                simulateLocationPermission();
            }
        }
        random = new Random();
        try {
            locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
            locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false,
                    true, false, false, true,
                    true, true, 0, 5);
            locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
        } catch (SecurityException e) {
            simulateLocationPermission();
        }
    }

    // 初始化websocket
    private void initWebsocket() {
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .pingInterval(15, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .build();
        wsManager = new WsManager.Builder(this)
                .wsUrl(wssHost)
                .needReconnect(true)
                .client(okHttpClient)
                .build();
        wsManager.setWsStatusListener(new WsStatusListener() {
            @Override
            public void onOpen(Response response) {
                super.onOpen(response);
            }

            @Override
            public void onMessage(String text) {
                super.onMessage(text);
            }

            @Override
            public void onMessage(ByteString bytes) {
                requestSuccess = true;
                super.onMessage(bytes);
                byte[] bs = bytes.toByteArray();
                byte[] buffer = new byte[bs.length-4];
                System.arraycopy(bytes.toByteArray(), 4, buffer, 0, bs.length-4);
                String j = new String(buffer);
                try {
                    JSONObject json = new JSONObject(j);
                    int retcode = json.getInt("retcode");
                    if (retcode == 0) {
                        if (saveStatus == 2) {
                            setToken();
                        }
                    } else {
                        getToken();
                    }
                    saveStatus = 1;
                    jsonArray = json.getJSONArray("sprite_list");
                    formatPets(jsonArray);
                    //onClickNext();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onReconnect() {
                super.onReconnect();
            }

            @Override
            public void onClosing(int code, String reason) {
                super.onClosing(code, reason);
                onReconnect();
            }

            @Override
            public void onClosed(int code, String reason) {
                super.onClosed(code, reason);
                onReconnect();
            }

            @Override
            public void onFailure(Throwable t, Response response) {
                super.onFailure(t, response);
                onReconnect();
            }
        });
        wsManager.startConnect();
    }

    private void onClickMod() {
        modType += 1;
        modType = modType % 4;
        switch(modType) {
            case 0:
                modButton.setText("妖");
                autoButton.setText("搜");
                break;
            case 1:
                modButton.setText("鼓");
                autoButton.setText("存");
                break;
            case 2:
                modButton.setText("擂");
                autoButton.setText("存");
                break;
            case 3:
                modButton.setText("石");
                autoButton.setText("存");
                break;
        }
    }

    private void onClickSave() {
        new AlertDialog.Builder(this).setTitle("确定提交吗?")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        saveStatus = 2;
                        getPets(latSpan, longtitude);
                        //setToken();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                })
                .show();
    }

    private void setToken() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL("http://gt.buxingxing.com/api/v1/token");
                    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                    conn.setDoOutput(true);
                    conn.setDoInput(true);
                    conn.setReadTimeout(5000);
                    conn.setConnectTimeout(5000);
                    conn.setUseCaches(false);
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Content-Type", "application/json");
                    conn.connect();
                    DataOutputStream out = new DataOutputStream(conn.getOutputStream());
                    JSONObject body = new JSONObject();
                    body.put("openid", openid);
                    body.put("token", gwgo_token);
                    String json = java.net.URLEncoder.encode(body.toString(), "utf-8");
                    out.writeBytes(json);
                    out.flush();
                    out.close();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    String lines;
                    StringBuffer sb = new StringBuffer("");
                    while((lines = reader.readLine()) != null) {
                        lines = URLDecoder.decode(lines, "utf-8");
                        sb.append(lines);
                    }
                    reader.close();
                    conn.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        fixedThreadPool.execute(runnable);
    }

    private void getToken() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                //Looper.prepare();
                try {
                    URL url = new URL("http://gt.buxingxing.com/api/v1/token");
                    //URL url = new URL("http://api.eiiku.com/zhuoyaoleida/api.php");
                    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                    conn.setReadTimeout(5000);
                    conn.setConnectTimeout(5000);
                    conn.setRequestMethod("GET");
                    conn.connect();
                    InputStream inputStream = null;
                    BufferedReader reader = null;
                    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        inputStream = conn.getInputStream();
                        reader = new BufferedReader(new InputStreamReader(inputStream));
                        String result = reader.readLine();
                        Log.i("token_result", result);
                        JSONObject data = new JSONObject(result);
                        Log.i("gwgo_token", data.toString());
                        gwgo_token = data.getJSONObject("data").get("token").toString();
                        openid = data.getJSONObject("data").get("openid").toString();
                        openidText.setText(openid);
                        tokenText.setText(gwgo_token);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        fixedThreadPool.execute(runnable);
    }

    private void formatPets(JSONArray ja) {
        JSONArray tmpJsonArray = new JSONArray();
        for (int i = 0; i < ja.length(); i ++) {
            try {
                JSONObject pet = ja.getJSONObject(i);
                int petId = pet.getInt("sprite_id");
                if (!allPetSet.contains(petId)) {
                    Log.i("NNNN:", String.valueOf(petId));
                }
                if (selectedPetSet.contains(petId)) {
                    double tmpNextLatitude = (double)pet.getInt("latitude") / (1000 * 1000);
                    double tmpNextLongtitude = (double)pet.getInt("longtitude") / (1000 * 1000);
                    GPS gps = gcj2gps84(tmpNextLatitude, tmpNextLongtitude);
                    pet.put("latitude", gps.getLat());
                    pet.put("longtitude", gps.getLon());
                    int gentime = pet.getInt("gentime");
                    int lifetime = pet.getInt("lifetime");
                    pet.put("endtime", gentime + lifetime);
                    tmpJsonArray.put(pet);
                    showPetToMap(petId, gps.getLat(), gps.getLon());
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        // 给petJsonArray重新赋值
        petJsonArray = tmpJsonArray;
        currentIndex = petJsonArray.length() - 1;
        if (petJsonArray.length() == 0) {
            toast = Toast.makeText(getApplicationContext(), "无结果,请更改位置或增加筛选妖灵", Toast.LENGTH_LONG);
        } else {
            toast = Toast.makeText(getApplicationContext(), "搜索完毕", Toast.LENGTH_SHORT);
        }
        toast.show();
    }

    // 显示妖灵到地图上
    private void showPetToMap(int petId, double lat, double lon) {
        tencentMap.addMarker(new MarkerOptions()
                .anchor(0.5f, 0.5f)
                .position(new LatLng(lat, lon))
                .icon(BitmapDescriptorFactory.fromBitmap(Bitmap.createScaledBitmap(headBitmaps.get(petId), dpi2pix(30), dpi2pix(30), true)))
                .draggable(true));
    }

    private void clearPetsFromMap() {
        tencentMap.clearAllOverlays();
        isMarker = false;
    }

    private void getPets(double lat, double lon) {
        clearPetsFromMap();
        toast = Toast.makeText(getApplicationContext(), "搜索中...", Toast.LENGTH_SHORT);
        toast.show();
        try {
            jsonObject = new JSONObject();
            jsonObject.put("request_type", "1001");
            jsonObject.put("latitude", (int)(lat*1000*1000));
            jsonObject.put("longtitude", (int)(lon*1000*1000));
            jsonObject.put("platform", 0);
            jsonObject.put("appid", appid);
            jsonObject.put("openid", openid);
            jsonObject.put("gwgo_token", gwgo_token);
            // 保证requestId为七位数字
            requestId = System.currentTimeMillis() % (10 * 1000 * 1000);
            jsonObject.put("requestid", requestId);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        String json = jsonObject.toString();
        int length = json.length();
        byte[] jsonByte = json.getBytes();
        byte[] buffer = new byte[4+length];
        length += 4;
        buffer[0] = (byte)(length & 0xFF000000);
        buffer[1] = (byte)(length & 0xFF0000);
        buffer[2] = (byte)(length & 0xFF00);
        buffer[3] = (byte)(length & 0xFF);
        System.arraycopy(jsonByte, 0, buffer, 4, jsonByte.length);
        final ByteString bytes = ByteString.of(buffer);
        // if (!wsManager.isWsConnected()) {
        //     wsManager.startConnect();
        // }
        // wsManager.sendMessage(bytes);

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                requestSuccess = false;
                int try_count = 5;
                while (try_count > 0) {
                    if (requestSuccess) {
                        break;
                    }
                    wsManager.sendMessage(bytes);
                    try_count --;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        fixedThreadPool.execute(runnable);
    }

    // 初始化控制悬浮窗
    private void initController() {
        // 悬浮窗参数
        controllerLayoutParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            controllerLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            controllerLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        controllerLayoutParams.format = PixelFormat.RGBA_8888;
        controllerLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        controllerLayoutParams.gravity = Gravity.START | Gravity.TOP;
        // 这是悬浮窗的宽高
        controllerLayoutParams.width = dpi2pix(100);
        controllerLayoutParams.height = dpi2pix(340);
        // 这是悬浮窗处于屏幕的位置
        controllerLayoutParams.x = metrics.widthPixels;
        controllerLayoutParams.y = metrics.heightPixels / 2 - dpi2pix(240) / 2;

        // 悬浮窗各个组件
        stopButton = controllerView.findViewById(R.id.stopButton);
        autoButton = controllerView.findViewById(R.id.autoButton);
        backButton = controllerView.findViewById(R.id.backButton);
        filterButton = controllerView.findViewById(R.id.filterButton);
        mapButton = controllerView.findViewById(R.id.mapButton);
        nextButton = controllerView.findViewById(R.id.nextButton);
        patrolButton = controllerView.findViewById(R.id.patrolButton);
        modButton = controllerView.findViewById(R.id.modButton);
        // 这里是控制移动速度的,有一个基础速度,然后根据速度条的位置增加相应的速度值
        // 因为这里调用了其它layout内的元素,所以需要用LayoutInflater获取到对应的layout再操作
        speedSeekBar = (SeekBar) controllerView.findViewById(R.id.speedSeekBar);
        speedSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                speed = baseSpeed + baseSpeed * (i / 30);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
        // 摇杆功能,监听旋转角度,根据角度来进行方向移动
        rockerView = controllerView.findViewById(R.id.rockerView);
        rockerView.setCallBackMode(RockerView.CallBackMode.CALL_BACK_MODE_STATE_CHANGE);
        rockerView.setOnAngleChangeListener(new RockerView.OnAngleChangeListener() {
            @Override
            public void onStart() {
            }

            @Override
            public void angle(double v) {
                angle = v;
            }

            @Override
            public void onFinish() {

            }
        });
    }

    // 显示控制悬浮窗
    private void showController() {
        if (Settings.canDrawOverlays(this)) {
            // 这就是去获取activity_controller,这样才能用它里面的元素
            windowManager.addView(controllerView, controllerLayoutParams);
        }
    }

    // 初始化筛选
    private void initFilter() {
        headLinearLayout = (LinearLayout) filterView.findViewById(R.id.headLinearLayout);
        // 筛选悬浮窗参数
        filterLayoutParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            filterLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            filterLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        filterLayoutParams.format = PixelFormat.RGBA_8888;
        filterLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        filterLayoutParams.gravity = Gravity.START | Gravity.TOP;
        // 这是悬浮窗的宽高
        filterLayoutParams.width = metrics.widthPixels;
        filterLayoutParams.height = metrics.heightPixels;
        // 这是悬浮窗处于屏幕的位置
        int width = (metrics.widthPixels - 110) / 10;
        int height = width;
        headLayoutParams = new LayoutParams(width, height);
        headLayoutParams.setMargins(5, 5, 5, 5);

        // 获取assets下的小妖头像
        assetManager = this.getResources().getAssets();
        try {
            // 将所有头像都放到assets/heads下,避免其它图片干扰
            headImages = assetManager.list("heads");
        } catch(IOException e) {
            e.printStackTrace();
        }
        int col = (int)Math.ceil(headImages.length / 10);
        filterLayoutParams.x = 5;
        filterLayoutParams.y = (metrics.heightPixels - col * 10 - width * col) / 2 - 150;
        filterLayoutParams.height = col * 10 + width * col + 300;
        // 记录小妖当前是否被选,以小妖id为key,false为未选、true为已选
        petSharedPreferences = getSharedPreferences("pet", this.MODE_PRIVATE);
        editor = petSharedPreferences.edit();
        petSet = new HashSet<String>(petSharedPreferences.getStringSet("selected", new HashSet<String>()));
        for (String str : petSet) {
            selectedPetSet.add(Integer.valueOf(str));
        }

        drums = petSharedPreferences.getString("drum", "");
        String [] tmpDrums = drums.split(",");
        Log.i("tmptmp", String.valueOf(tmpDrums.length));
        if (tmpDrums.length > 1) {
            for (int i = 0; i < tmpDrums.length; i += 2) {
                drumLocations.add(Double.valueOf(tmpDrums[i]));
                drumLocations.add(Double.valueOf(tmpDrums[i+1]));
            }
        }

        battlefields = petSharedPreferences.getString("battlefield", "");
        String [] tmpBattlefields = battlefields.split(",");
        if (tmpBattlefields.length > 1) {
            for (int i = 0; i < tmpBattlefields.length; i += 2) {
                battlefieldLocations.add(Double.valueOf(tmpBattlefields[i]));
                battlefieldLocations.add(Double.valueOf(tmpBattlefields[i+1]));
            }
        }

        stones = petSharedPreferences.getString("stone", "");
        String [] tmpStones = stones.split(",");
        if (tmpStones.length > 1) {
            for (int i = 0; i < tmpStones.length; i += 2) {
                stoneLocations.add(Double.valueOf(tmpStones[i]));
                stoneLocations.add(Double.valueOf(tmpStones[i+1]));
            }
        }
    }

    // 显示筛选界面
    private void showFilter() {
        if (Build.VERSION.SDK_INT > 22) {
            if (Settings.canDrawOverlays(this)) {
                windowManager.addView(filterView, filterLayoutParams);
            }
        }
        //showPets();
    }
    private void initFloatMap() {
        floatMapViewParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            floatMapViewParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            floatMapViewParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        floatMapViewParams.format = PixelFormat.RGBA_8888;
        floatMapViewParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        floatMapViewParams.gravity = Gravity.START | Gravity.TOP;
        floatMapViewParams.width = metrics.widthPixels - 40;
        floatMapViewParams.x = 40 / 2;
        floatMapViewParams.height = metrics.heightPixels - 40 * (metrics.heightPixels / metrics.widthPixels);
        floatMapViewParams.y = (metrics.heightPixels - floatMapViewParams.height) / 2;
        LinearLayout floatMapLinearLayout = (LinearLayout)floatMapView.findViewById(R.id.floatmaplinearlayout);
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)floatMapLinearLayout.getLayoutParams();
        params.width = floatMapViewParams.width;
        params.height = floatMapViewParams.height - 200;
        floatMapLinearLayout.setLayoutParams(params);
        floatMapCloseButton = floatMapView.findViewById(R.id.closefloatmapbutton);
        showFloatMap();
    }

    //显示地图悬浮窗
    private void showFloatMap() {
        if (Build.VERSION.SDK_INT > 22) {
            if (Settings.canDrawOverlays(this)) {
                windowManager.addView(floatMapView, floatMapViewParams);
            }
        }
    }
    //隐藏地图悬浮窗
    private void removeFloatMap() {
        windowManager.removeView(floatMapView);
    }

    private void initPets() {
        // 获取assets下的小妖头像
        assetManager = this.getResources().getAssets();
        try {
            // 将所有头像都放到assets/heads下,避免其它图片干扰
            headImages = assetManager.list("heads");
        } catch(IOException e) {
            e.printStackTrace();
        }
        InputStream input = null;
        for (int i = 0; i < headImages.length; i ++) {
            int petId = Integer.valueOf(headImages[i].substring(0, headImages[i].indexOf(".")));
            allPetSet.add(petId);
            try {
                input = assetManager.open(headImages[i]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            headBitmaps.put(petId, BitmapFactory.decodeStream(input));
        }
    }

    // 显示小妖头像
    // 这里就是读取assets中的图片,一排显示10个
    private void showPets() {
        InputStream input = null;
        LinearLayout imageLinearLayout = null;
        int count = 0;
        for (int petId : allPetSet) {
            // 每十个一换行
            if (count % 10 == 0) {
                imageLinearLayout = new LinearLayout(this);
                imageLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
                headLinearLayout.addView(imageLinearLayout);
            }
            count ++;
            final ImageView imgView = new ImageView(this);
            imgView.setLayoutParams(headLayoutParams);
            imgView.setImageBitmap(headBitmaps.get(petId));
            imgView.setId(petId);
            if (selectedPetSet.contains(petId)) {
                imgView.setAlpha(clickHeadAlpha);
            } else {
                imgView.setAlpha(unclickHeadAlpha);
            }
            // 监听图标点击事件来切换选中与未选中状态
            imgView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int imageId = view.getId();
                    if (selectedPetSet.contains(imageId)) {
                        petSet.remove(String.valueOf(imageId));
                        selectedPetSet.remove(imageId);
                        view.setAlpha(unclickHeadAlpha);
                    } else {
                        petSet.add(String.valueOf(imageId));
                        selectedPetSet.add(imageId);
                        view.setAlpha(clickHeadAlpha);
                    }
                    // 每一次改变,都将数据写入到SharedPreferences,以便保存用户数据
                    editor.putStringSet("selected", petSet);
                    editor.commit();
                }
            });
            imageLinearLayout.addView(imgView);
        }
    }
    // 隐藏筛选界面
    private void removeFilter() {
        windowManager.removeView(filterView);
    }

    public void onClick(View view) {
        setButtonColor((Button)view);
        switch (view.getId()) {
            case R.id.stopButton:
                onClickOnOff();
                break;
            case R.id.backButton:
                onClickBack();
                break;
            case R.id.filterButton:
                onClickFilter();
                break;
            case R.id.autoButton:
                onClickAuto();
                break;
            case R.id.closeFilterButton:
                removeFilter();
                break;
            case R.id.mapButton:
                onClickFloatMap();
                break;
            case R.id.closefloatmapbutton:
                removeFloatMap();
                break;
            case R.id.nextButton:
                onClickNext();
                break;
            case R.id.patrolButton:
                //onPatrolClick();
                //setToken();
                getToken();
                break;
            case R.id.saveButton:
                onClickSave();
                //setToken();
                break;
            case R.id.modButton:
                onClickMod();
                break;
        }
    }
    // dpi转pix
    private int dpi2pix(float dpi) {
        return (int)(dpi * metrics.density + 0.5f);
    }

    // 控制面板是展开还是收回的方法,由backButton调用
    // 主要就是重新设置悬浮窗的宽度,然后更新悬浮窗
    public void onClickBack() {
        isBack += 1;
        if (isBack % 2 == 1) {
            // controllerLayoutParams.width = 260 / 2 - 10;
            controllerLayoutParams.width = dpi2pix(50);
            // controllerLayoutParams.height = (260 / 2 - 10) * 2;
            controllerLayoutParams.height = dpi2pix(150);
            windowManager.updateViewLayout(controllerView, controllerLayoutParams);
            backButton.setText("开");
        } else {
            controllerLayoutParams.width = dpi2pix(100);
            controllerLayoutParams.height = dpi2pix(340);
            windowManager.updateViewLayout(controllerView, controllerLayoutParams);
            backButton.setText("收");
        }
    }
    // 设置要筛选小妖
    public void onClickFilter() {
        showFilter();
    }
    private void onClickFloatMap() {
        initFloatMap();
    }
    private void onClickAuto() {
        if (modType == 0) {
            getPets(latitude, longtitude);
        } else {
            saveLocation();
        }
    }
    private void saveLocation() {
        if (latitude < 1 || longtitude < 1) {
            return;
        }
        switch (modType) {
            case 1:
                if (drums == "") {
                    drums = latitude + ","+ longtitude;
                } else {
                    drums = drums + "," + latitude + ","+ longtitude;
                }
                drumLocations.add(latitude);
                drumLocations.add(longtitude);
                editor.putString("drum", drums);
                editor.commit();
                break;
            case 2:
                if (battlefields == "") {
                    battlefields = latitude + ","+ longtitude;
                } else {
                    battlefields = battlefields + "," + latitude + ","+ longtitude;
                }
                battlefieldLocations.add(latitude);
                battlefieldLocations.add(longtitude);
                editor.putString("battlefield", battlefields);
                editor.commit();
                break;
            case 3:
                if (stones == "") {
                    stones = latitude + ","+ longtitude;
                } else {
                    stones = stones + "," + latitude + ","+ longtitude;
                }
                stoneLocations.add(latitude);
                stoneLocations.add(longtitude);
                editor.putString("stone", stones);
                editor.commit();
                break;
        }
        Toast toast = Toast.makeText(getApplicationContext(), "保存成功", Toast.LENGTH_SHORT);
        toast.show();
    }
    public void onClickNext() {
        if (modType == 0) {
            goToNextPet();
        } else if (modType == 1){
            goToNextDrum();
        } else if (modType == 2) {
            goToNextBattlefield();
        } else if(modType == 3) {
            goToNextStone();
        }
    }
    private void goToNextStone() {
        if (stoneLocations.size() > 0) {
            moveTo(stoneLocations.get(stoneIndex), stoneLocations.get(stoneIndex+1));
            stoneIndex += 2;
            stoneIndex = stoneIndex % stoneLocations.size();
        } else {
            Toast toast = Toast.makeText(getApplicationContext(), "暂无记录点", Toast.LENGTH_SHORT);
            toast.show();
        }
    }
    private void goToNextDrum() {
        if (drumLocations.size() > 0) {
            moveTo(drumLocations.get(drumIndex), drumLocations.get(drumIndex+1));
            drumIndex += 2;
            drumIndex = drumIndex % drumLocations.size();
        } else {
            Toast toast = Toast.makeText(getApplicationContext(), "暂无记录点", Toast.LENGTH_SHORT);
            toast.show();
        }
    }
    private void goToNextBattlefield() {
        if (battlefieldLocations.size() > 0) {
            moveTo(battlefieldLocations.get(battlefieldIndex), battlefieldLocations.get(battlefieldIndex+1));
            battlefieldIndex += 2;
            battlefieldIndex = battlefieldIndex % battlefieldLocations.size();
        } else {
            Toast toast = Toast.makeText(getApplicationContext(), "暂无记录点", Toast.LENGTH_SHORT);
            toast.show();
        }
    }
    // 自动到小妖身边
    public void goToNextPet() {
        // 我这里逆序查找,因为,一般后台的妖灵都比较好
        double nextLatitude = 0;
        double nextLongtitude = 0;
        if (petJsonArray != null && petJsonArray.length() > 0 && currentIndex >= 0) {
            for (; currentIndex >= 0; currentIndex --) {
                try {
                    JSONObject currentPet = petJsonArray.getJSONObject(currentIndex);
                    nextLatitude = currentPet.getDouble("latitude");
                    nextLongtitude = currentPet.getDouble("longtitude");
                    final int sprite_id = currentPet.getInt("sprite_id");
                    int endtime = currentPet.getInt("endtime");
                    long currentTime = System.currentTimeMillis() / 1000;
                    if (selectedPetSet.contains(sprite_id) && endtime > (currentTime + 2)) {
                        break;
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            // 如果循环退出时,currentIndex大于等于0就说明是break出来的
            if (currentIndex >= 0) {
                moveTo(nextLatitude, nextLongtitude);
                currentIndex --;
            } else {
                getPets(latitude, longtitude);
            }
        } else {
            getPets(latitude, longtitude);
        }
    }
    private void moveTo(final double lat, final double lon) {
        Runnable runnable =  new Runnable() {
            @Override
            public void run() {
                final double latitudeStep = (lat - latitude) / 3000;
                final double longtitudeStep = (lon - longtitude) / 3000;
                // 这里我想的是,用3秒走到对应的坐标
                for (int i = 1; i < 3000; i ++) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    latitude += latitudeStep;
                    longtitude += longtitudeStep;
                    //setLocation(latitude, longtitude);
                }
                // 最后直接将要去的坐标进行赋值,保证是正确的位置
                latitude = lat;
                longtitude = lon;
            }
        };
        fixedThreadPool.execute(runnable);
    }
    // 控制走与停的方法,由stopButton调用
    public void onClickOnOff() {
        isRun += 1;
        if (isRun % 2 == 0) {
            stopButton.setText("走");
        } else {
            stopButton.setText("停");
        }
    }

    // 这里tencent定位监听的回调,只要位置发生变化,就会调用此方法
    // 我这里就是让定位获取的坐标始终位于地图中央
    @Override
    public void onLocationChanged(TencentLocation location, int error, String reason) {
        if (latitude == 0 && longtitude == 0) {
            latitude = location.getLatitude();
            longtitude = location.getLongitude();
            Toast toast = Toast.makeText(getApplicationContext(), "定位成功", Toast.LENGTH_SHORT);
            toast.show();
        }
        // 自动点击屏幕操作
        // int x = metrics.widthPixels / 2;
        // int y = metrics.heightPixels / 2 - 50 * 3 / 2;
        // String[] order = {"input", "tap", "" + x, "" + y};
        // try {
        //     new ProcessBuilder(order).start();
        // } catch (IOException e) {
        //     e.printStackTrace();
        // }


        if (firstLocation && latitude != 0 && longtitude != 0) {
            firstLocation = false;
            tencentMap.setCenter(new LatLng(latitude, longtitude));
        }
        if (!isMarker) {
            marker = tencentMap.addMarker(new MarkerOptions()
                    .icon(BitmapDescriptorFactory.defaultMarker())
                    .draggable(true));
            isMarker = true;
        }
        marker.setPosition(new LatLng(latitude, longtitude));
    }

    @Override
    public void onStatusUpdate(String name, int status, String desc) {

    }

    private void setButtonColor(Button btn) {
        int alpha = genInt(0x8D, 0xEF);
        btn.setBackgroundColor((alpha<<24) | random.nextInt(0x00FFFFFF));
    }

    // 生成一个区间的浮点数
    private double genDouble(final double min, final double max) {
        return min + ((max - min) * random.nextDouble());
    }

    // 生成一个区间的整数
    private int genInt(final int min, final int max) {
        return random.nextInt(max) % (max-min+1) + min;
    }

    private void setLocation(double longtitude, double latitude) {

        // 因为我是在北京的,我把这个海拔设置了一个符合北京的范围,随机生成
        altitude = genDouble(38.0, 50.5);
        // 而定位有精度,GPS精度一般小于15米,我设置在1到15米之间随机
        accuracy = (float)genDouble(1.0, 15.0);

        // 下面就是自己设置定位的位置了
        Location location = new Location(LocationManager.GPS_PROVIDER);
        location.setTime(System.currentTimeMillis());
        location.setLatitude(latitude);
        location.setLongitude(longtitude);
        // 北京海拔大概范围,随机生成
        location.setAltitude(altitude);
        // GPS定位精度范围,随机生成
        location.setAccuracy(accuracy);
        if (Build.VERSION.SDK_INT > 16) {
            location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
        }
        try {
            locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, location);
        } catch (SecurityException e) {
            simulateLocationPermission();
        }
    }

    public void continueLocation2() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                while (true) {
                    try {
                        // 这里是一个死循环,但是我们不可以直接不停的设置定位,那样会把手机卡死
                        // 因此我们这里需要设置两次设置定位的间隔, 但是这个值又不能设置大了,
                        // 因为,两次定位之间间隔长了,在这个时间窗口有其它程序调用定位功能,就会获取到你真实的位置
                        // 从而导致,位置出现跳跃的现象,我这里设置1毫秒
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // isRun是来判断我们是不是要停下来,记住,这里停下来的概念是,你的位置坐标不变的意思,
                    // 因此,要达到这个效果,并不是要把线程停下来,而是要不停的给设置同一位置坐标
                    if (isRun % 2 == 1) {
                        // 这里设置四个方向,北:0、东:1、南:2、西:3
                        // 改变了方向就改变经纬度的变化策略
                        if (isPatrol % 2 == 0) {
                            if ( angle >= 0 && angle < 90) {
                                double radinas = Math.toRadians(angle);
                                latitude -= Math.sin(radinas) * speed;
                                longtitude += Math.cos(radinas) * speed;
                            } else if (angle >= 90 && angle < 180) {
                                double radinas = Math.toRadians(180 - angle);
                                latitude -= Math.sin(radinas) * speed;
                                longtitude -= Math.cos(radinas) * speed;
                            } else if (angle >= 180 && angle < 270) {
                                double radinas = Math.toRadians(angle - 180);
                                latitude += Math.sin(radinas) * speed;
                                longtitude -= Math.cos(radinas) * speed;
                            } else {
                                double radinas = Math.toRadians(360 - angle);
                                latitude += Math.sin(radinas) * speed;
                                longtitude += Math.cos(radinas) * speed;
                            }
                        } else {
                            // 每走多少步后换方向
                            if (count % loop == 0) {
                                angle += 90;
                                angle %= 360;
                                if (angle == 270) {
                                    loop += step;
                                    count = 1;
                                }
                            }
                            count += 1;
                            if (angle == 0) {
                                longtitude += patrolSpeed;
                            } else if (angle == 90) {
                                latitude -= patrolSpeed;
                            } else if (angle == 180) {
                                longtitude -= patrolSpeed;
                            } else if (angle == 270) {
                                latitude += patrolSpeed;
                            }
                        }
                    }
                    setLocation(longtitude, latitude);
                }
            }
        };
        fixedThreadPool.execute(runnable);
    }

    // 持续定位
    public void continueLocation() {
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                while (true) {
                    try {
                        // 这里是一个死循环,但是我们不可以直接不停的设置定位,那样会把手机卡死
                        // 因此我们这里需要设置两次设置定位的间隔, 但是这个值又不能设置大了,
                        // 因为,两次定位之间间隔长了,在这个时间窗口有其它程序调用定位功能,就会获取到你真实的位置
                        // 从而导致,位置出现跳跃的现象,我这里设置1毫秒
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // isRun是来判断我们是不是要停下来,记住,这里停下来的概念是,你的位置坐标不变的意思,
                    // 因此,要达到这个效果,并不是要把线程停下来,而是要不停的给设置同一位置坐标
                    if (isRun % 2 == 1) {
                        // 这里设置四个方向,北:0、东:1、南:2、西:3
                        // 改变了方向就改变经纬度的变化策略
                        if (isPatrol % 2 == 0) {
                            if ( angle >= 0 && angle < 90) {
                                double radinas = Math.toRadians(angle);
                                latitude -= Math.sin(radinas) * speed;
                                longtitude += Math.cos(radinas) * speed;
                            } else if (angle >= 90 && angle < 180) {
                                double radinas = Math.toRadians(180 - angle);
                                latitude -= Math.sin(radinas) * speed;
                                longtitude -= Math.cos(radinas) * speed;
                            } else if (angle >= 180 && angle < 270) {
                                double radinas = Math.toRadians(angle - 180);
                                latitude += Math.sin(radinas) * speed;
                                longtitude -= Math.cos(radinas) * speed;
                            } else {
                                double radinas = Math.toRadians(360 - angle);
                                latitude += Math.sin(radinas) * speed;
                                longtitude += Math.cos(radinas) * speed;
                            }
                        } else {
                            // 每走多少步后换方向
                            if (count % loop == 0) {
                                angle += 90;
                                angle %= 360;
                                if (angle == 270) {
                                    loop += step;
                                    count = 1;
                                }
                            }
                            count += 1;
                            if (angle == 0) {
                                longtitude += patrolSpeed;
                            } else if (angle == 90) {
                                latitude -= patrolSpeed;
                            } else if (angle == 180) {
                                longtitude -= patrolSpeed;
                            } else if (angle == 270) {
                                latitude += patrolSpeed;
                            }
                        }
                    }
                    setLocation(longtitude, latitude);
                }
            }
        });
        thread.start();
    }

    // 巡逻
    private void onPatrolClick() {
        isRun += 1;
        isPatrol += 1;
        angle = 0;
        count = 1;
        loop = 10000;
    }

    private class GPS {
        private double lat;
        private double lon;
        public GPS(double lat, double lon) {
            this.lat = lat;
            this.lon = lon;
        }
        public double getLat() {
            return lat;
        }
        public double getLon() {
            return lon;
        }
        public void setLat(double lat) {
            this.lat = lat;
        }
        public void setLon(double lon) {
            this.lon = lon;
        }
    }

    // GCJ02坐标转GPS84
    private GPS gcj2gps84(double lat, double lon) {
        double dLat = transLat(lon - 105.0, lat - 35.0);
        double dLon = transLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        mgLat = lat * 2 - mgLat;
        mgLon = lon * 2 - mgLon;
        return new GPS(mgLat, mgLon);
    }
    private double transLat(double x, double y) {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
        return ret;
    }
    private double transLon(double x, double y) {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
        return ret;
    }

    // 悬浮窗提示
    private void floatWindowPermission() {
        new AlertDialog.Builder(this)
                .setTitle("启用悬浮窗")
                .setMessage(("必须开启此权限"))
                .setPositiveButton("设置",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                try {
                                    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
                                    startActivity(intent);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                    }
                })
                .show();
    }

    // 模拟定位的权限
    private void simulateLocationPermission() {
        new AlertDialog.Builder(this)
                .setTitle("启用模拟位置")
                .setMessage("在开发者选项中模拟位置应用选择此程序")
                .setPositiveButton("设置", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        try {
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
                            startActivity(intent);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                    }
                })
                .show();
    }

    // 获取下一次定位点
    private void getNextLocation() {

    }
}