package com.abbidot.tracker.ui.fragment.map.googlemap

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Point
import android.location.Location
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.abbidot.baselibrary.constant.MMKVKey
import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.LogUtil
import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.tracker.R
import com.abbidot.tracker.base.BaseFragment
import com.abbidot.tracker.bean.FencesBean
import com.abbidot.tracker.bean.HistoryDataBean
import com.abbidot.tracker.bean.MapDeviceBean
import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.databinding.FragmentGoogleMapBinding
import com.abbidot.tracker.util.ImageUtil
import com.abbidot.tracker.util.LonAndLatUtil
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.util.ViewUtil
import com.abbidot.tracker.widget.MapDeviceNetView
import com.abbidot.tracker.widget.MapMarkerInfoView
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.maps.CameraUpdate
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.GoogleMapOptions
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.Circle
import com.google.android.gms.maps.model.CircleOptions
import com.google.android.gms.maps.model.CustomCap
import com.google.android.gms.maps.model.Dash
import com.google.android.gms.maps.model.Gap
import com.google.android.gms.maps.model.JointType
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.gms.maps.model.PatternItem
import com.google.android.gms.maps.model.Polygon
import com.google.android.gms.maps.model.PolygonOptions
import com.google.android.gms.maps.model.Polyline
import com.google.android.gms.maps.model.PolylineOptions
import com.google.android.gms.maps.model.RoundCap
import com.google.android.gms.tasks.CancellationTokenSource
import com.google.android.gms.tasks.Task
import com.qmuiteam.qmui.util.QMUIDisplayHelper
import kotlinx.coroutines.launch


/**
 * 谷歌地图
 */
abstract class BaseGoogleMapFragment :
    BaseFragment<FragmentGoogleMapBinding>(FragmentGoogleMapBinding::inflate), OnMapReadyCallback {

    var mGoogleMap: GoogleMap? = null
    private var mGoogleMapView: MapView? = null

    /**地图样式类型:卫星/标准
     * GoogleMap.MAP_TYPE_NONE 不显示地图
     * GoogleMap.MAP_TYPE_NORMAL 标准普通地图
     * GoogleMap.MAP_TYPE_SATELLITE 卫星地图
     * GoogleMap.MAP_TYPE_TERRAIN 地形，地势
     * GoogleMap.MAP_TYPE_HYBRID 混合的
     */
//    private var mMapType = GoogleMap.MAP_TYPE_NORMAL

    private var mMapviewBundleKey = this.javaClass.simpleName

    //地图放大
    private var mGoogleMapZoom = 17f

    //地图摄像机移动动画时间 毫秒
    private val mAnimMoveDurationMs = 800

    //自定显示宠物头像地点信息图层
    var mMarker: Marker? = null

    //自定显示用户地点信息图层
    var mUserMarker: Marker? = null

    //宠物大头针设置自定义头像
    private var mPetHeadIconBitmap: Bitmap? = null

    private var mMarkerInfoWindowAdapter: MarkerInfoWindowAdapter? = null

    //宠物头像地址
    var mPetHeadUrl = ""

    //头像为空，用默认类型的头像
    private var mPetType = ConstantInt.DogPetType

    //地图是否加载准备好了
    var isMapLoadOk = false

    //用户位置经纬度
    var mUserLatLng: LatLng? = null

    //宠物位置经纬度
    var mPetLatLng: LatLng? = null

    //第一次执行定位回调，方便只刷新用户位置
    private var isLocationSuccessCallback = true

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {
        mViewBinding = this.inflater(inflater, container, false)
        LogUtil.e("${mMapviewBundleKey}===GoogleMapFragment--->onCreateView---$container")

        var mapViewBundle: Bundle? = null
        if (null != savedInstanceState) {
            mapViewBundle = savedInstanceState.getBundle(mMapviewBundleKey)
        }
//        mGoogleMapView = mViewBinding.googleMapView

        //指定地图的初始照相机位置（指定 null 以使用 默认摄像机位置）
        val options = GoogleMapOptions().apply {
//            val options = GoogleMapOptions().liteMode(true)
            //默认华盛顿经纬度
            val lat = MMKVUtil.getDouble(MMKVKey.MapShowDefaultLat, 38.913611)
            val lon = MMKVUtil.getDouble(MMKVKey.MapShowDefaultLon, -77.013222)
            //不使用地图摄像头移动动画，默认级别一样大
            val position = CameraPosition.fromLatLngZoom(LatLng(lat, lon), mGoogleMapZoom)
            camera(position)
        }
        mGoogleMapView = MapView(this.requireActivity(), options)
        mGoogleMapView?.onCreate(mapViewBundle)
        mViewBinding.root.addView(mGoogleMapView)

        return mViewBinding.root
    }

    override fun initData() {
        super.initData()
        mGoogleMapView?.getMapAsync(this)
    }

    override fun onResume() {
        super.onResume()
        mGoogleMapView?.onResume()

        mGoogleMap?.apply {
            val mapTypeSp = Util.getMapTypeSp()
            if (mapTypeSp == ConstantInt.Type0 && mapType != GoogleMap.MAP_TYPE_NORMAL) {
                mapType = GoogleMap.MAP_TYPE_NORMAL
            } else if (mapTypeSp == ConstantInt.Type1 && mapType != GoogleMap.MAP_TYPE_HYBRID) {
                mapType = GoogleMap.MAP_TYPE_HYBRID
            }
        }
    }

    override fun onStart() {
        super.onStart()
        mGoogleMapView?.onStart()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)

        var mapViewBundle = outState.getBundle(mMapviewBundleKey)
        if (null == mapViewBundle) {
            mapViewBundle = Bundle()
            outState.putBundle(mMapviewBundleKey, mapViewBundle)
        }
        mGoogleMapView?.onSaveInstanceState(mapViewBundle)
    }

    override fun onPause() {
        super.onPause()
        mGoogleMapView?.onPause()
    }


    override fun onLowMemory() {
        super.onLowMemory()
        mGoogleMapView?.onLowMemory()
    }

    /**
     * 设置地图样式
     */
    private fun setGoogleMapType() {
        mGoogleMap?.apply {
            //地图样式
            val mapTypeSp = Util.getMapTypeSp()
            if (mapTypeSp == ConstantInt.Type0) {
                mapType = GoogleMap.MAP_TYPE_NORMAL
            } else if (mapTypeSp == ConstantInt.Type1) {
                mapType = GoogleMap.MAP_TYPE_HYBRID
            }
        }
    }

    /**
     * 设置地图显示级别
     */
    fun setGoogleMapZoom(zoom: Float) {
        mGoogleMapZoom = zoom
    }

    /**
     * 获取地图显示级别
     */
    fun getGoogleMapZoom() = mGoogleMapZoom

    /**
     * 卫星标准地图模式切换
     */
    fun switchSatelliteAndNormalMapType() {
        setGoogleMapType()
    }

    /**
     * 编辑围栏还原摄像机
     */
    private var mCameraUpdate: CameraUpdate? = null

    fun setCameraUpdateNull() {
        //只有刚进入页面才会使用,只用一次,方便搜索地址移动摄像头
        mCameraUpdate = null
    }

    /**
     * 设置缩放等级
     */
    fun setZoomTo(zoomLevel: Float) {
        mGoogleMap?.apply {
            mGoogleMapZoom *= zoomLevel
            moveCamera(CameraUpdateFactory.zoomTo(mGoogleMapZoom))
        }
    }

    /**
     * 根据CameraUpdate移动摄像机
     */
    fun moveCameraUpdate(lat: Double, lon: Double, isAnimMoveCamera: Boolean = false) {
        if (null == mCameraUpdate) {
            moveCameraLocation(lat, lon, isAnimMoveCamera)
            LogUtil.e("moveCameraUpdate---------->CameraUpdate=null,摄像机移动靠moveCameraLocation经纬度")
            return
        }
        mGoogleMap?.apply {
            if (isAnimMoveCamera) {
                animateCamera(mCameraUpdate!!, mAnimMoveDurationMs, null)
            } else {
                moveCamera(mCameraUpdate!!)
            }
        }

    }

    /**
     * 根据CameraUpdate移动摄像机
     */
    fun moveCameraUpdate(latLng: LatLng, isAnimMoveCamera: Boolean = false) {
        moveCameraUpdate(latLng.latitude, latLng.longitude, isAnimMoveCamera)
    }

    /**
     * 移动到某个位置 为中心点
     */
    fun moveCameraLocation(latLng: LatLng, isAnimMoveCamera: Boolean = false) {
        val newLatLng = toGCJ02LatLon(latLng)
        mGoogleMap?.apply {
            //animateCamera使用动画
            if (isAnimMoveCamera) {
                animateCamera(
                    CameraUpdateFactory.newLatLngZoom(newLatLng, mGoogleMapZoom),
                    mAnimMoveDurationMs,
                    null
                )
            } else {
                moveCamera(CameraUpdateFactory.newLatLngZoom(newLatLng, mGoogleMapZoom))
            }
        }
    }

    /**
     * 移动到某个位置 为中心点
     */
    fun moveCameraLocation(lat: Double, lon: Double, isAnimMoveCamera: Boolean = false) {
        moveCameraLocation(LatLng(lat, lon), isAnimMoveCamera)
    }

    /**
     *  切换用户和宠物的位置居中显示,移动摄像头中心
     */
    fun switchShowLocation(@ConstantInt type: Int) {
        when (type) {
            ConstantInt.PetLocationType -> {
                //刷新下用户当前的位置
                getLastLocation()
                mPetLatLng?.let {
                    mGoogleMapZoom = 17f
                    refreshPetCurrentLocation(it, true)
                }
            }

            ConstantInt.UserLocationType -> {
                mPetLatLng?.let {
                    mUserLatLng?.apply {
                        setLatLngZoom(mContext!!, 250, it, this)
                        cameraUpdateMove()
                    }
                }
            }

            else -> {

            }

//            ConstantInt.DefaultType -> {
//                mPetLatLng?.let {
//                    mGoogleMapZoom = 17f
//                    refreshPetCurrentLocation(it, true)
//                }
//            }

//            else -> {
//                mUserLatLng?.let {
//                    moveCameraLocation(it)
//                }
//            }
        }
    }

    /**
     * 移动到某个位置 为中心点,animateCamera使用动画
     */
    fun moveAnimateCameraLocation(
        latLng: LatLng, moveCameraCallback: GoogleMap.CancelableCallback?
    ) {
        val newLatLng = toGCJ02LatLon(latLng)
        //1秒动画执行时间
        mGoogleMap?.apply {
            animateCamera(
                CameraUpdateFactory.newLatLngZoom(newLatLng, mGoogleMapZoom),
                mAnimMoveDurationMs,
                moveCameraCallback
            )
        }
    }

    /**
     * 设置大头针宠物头像
     */
    fun setPetHeadIconUrl(petHeadUrl: String, petType: Int) {
        mPetHeadUrl = petHeadUrl
        mPetType = petType
        mPetHeadIconBitmap?.recycle()
        mPetHeadIconBitmap = null
    }

    fun latLngToScreenLocation(latLng: LatLng): Point {
        val points = Point(0, 0)
        mGoogleMap?.apply {
            val newLatLng = toGCJ02LatLon(latLng)
            projection.toScreenLocation(newLatLng).let {
                points.x = it.x
                points.y = it.y
            }
        }
        return points
    }

    /**
     * 设置宠物头像地图Marker
     */
    private suspend fun setPetHeadMarker(
        latLng: LatLng, headBgResId: Int = R.drawable.pic_map_gps_avatar
    ) {
        if (null == mPetHeadIconBitmap) {
            //设置头像
            mPetHeadIconBitmap =
                GoogleBitmapHelper.headToBitmap(mContext!!, headBgResId, mPetHeadUrl, mPetType)
        }
        val newLatLng = toGCJ02LatLon(latLng)
        val markerOptions = MarkerOptions().position(newLatLng)
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(mPetHeadIconBitmap!!))
        mMarker?.remove()
        mGoogleMap?.apply {
            mMarker = addMarker(markerOptions)
        }
        setUserMarker()
    }

    fun setUserMarker() {
        if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
            mUserLatLng?.let {
                if (null == mUserMarker) {
                    mUserMarker = addImageMarker(it, R.drawable.icon_user_location_image,false)
                } else {
                    if (it.latitude == mUserMarker!!.position.latitude && it.longitude == mUserMarker!!.position.longitude) {
                    } else {
                        mUserMarker?.remove()
                        mUserMarker = addImageMarker(it, R.drawable.icon_user_location_image,false)
                    }
                }
                mUserMarker?.setAnchor(0.5f,0.5f)
            }
        }
//        else {
//            mGoogleMap?.apply {
//                if (!isMyLocationEnabled) {
//                    //检测权限，开启用户的当前位置https://developers.google.cn/maps/documentation/android-sdk/location?hl=zh-cn
//                    if (ActivityCompat.checkSelfPermission(
//                            mContext!!, Manifest.permission.ACCESS_FINE_LOCATION
//                        ) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
//                            mContext!!, Manifest.permission.ACCESS_COARSE_LOCATION
//                        ) == PackageManager.PERMISSION_GRANTED
//                    ) {
//                        //启用“我的位置”图层。
//                        isMyLocationEnabled = true
//                    }
//                }
//            }
//        }
    }

    /**
     * 设置宠物当前位置经纬度
     */
    fun setPetCurrentLocation(petHeadUrl: String, lat: Double, lon: Double, petType: Int) {
        lifecycleScope.launch(lifecycleScope.coroutineContext) {
            setPetHeadIconUrl(petHeadUrl, petType)
            mPetLatLng = LatLng(lat, lon).apply {
                setPetHeadMarker(this)
            }
        }
    }

    /**
     * 当前宠物位置刷新
     * @param needMoveCamera 摄像机是否摄需要移动当前经纬度，地图中心
     * @param isAnimMoveCamera 动画移动地图摄像头
     */
    fun refreshPetCurrentLocation(
        latLng: LatLng,
        needMoveCamera: Boolean = true,
        isAnimMoveCamera: Boolean = false,
        headBgResId: Int = R.drawable.pic_map_gps_avatar
    ) {
        mPetLatLng = latLng

        if (null != mGoogleMap) {

            lifecycleScope.launch(lifecycleScope.coroutineContext) {

                setPetHeadMarker(latLng, headBgResId)

                //是否需要移动到地图中心点
                if (needMoveCamera) {
                    //animateCamera使用动画
                    moveCameraLocation(latLng, isAnimMoveCamera)
                }

                //刷新当前位置ok,延时等待移动地图摄像头动画
//                if (isAnimMoveCamera) {
//                    mGoogleMapView.postDelayed({
//                        onRefreshPetCurrentLocationOk(mGoogleMap!!)
//                    }, 1000)
//                } else {
//                    onRefreshPetCurrentLocationOk(mGoogleMap!!)
//                }
                mGoogleMapView?.postDelayed({
                    onRefreshPetCurrentLocationOk(mGoogleMap!!)
                }, 500)
            }
        }
    }

    /**
     * 清空所有图层
     */
    open fun clearAllMarker() {
        mGoogleMap?.clear()
        clearFenceList()
    }

    //在地图上画圆形围栏和多边形围栏集合
    private var mCircleFenceList: MutableList<Circle>? = null
    private var mPolygonFenceList: MutableList<Polygon>? = null

//    fun initFenceList() {
//        if (null == mCircleFenceList) mCircleFenceList = mutableListOf()
//        if (null == mRectFenceList) mRectFenceList = mutableListOf()
//    }

    /**
     * 地图上画形状,虚线风格
     */
    fun getDashedPatternStyle(patternLength: Float = 10f): List<PatternItem> {
        //自定义描边图案 https://developers.google.cn/maps/documentation/android-sdk/shapes#stroke_color
        return listOf(
            //图案设置成了重复的点序列，后跟一个长度为 20 像素的间隙、
            // 一个长度为 30 像素的短划线，以及另一个 20 像素的间隙。
//            Dot(),
            Gap(patternLength), Dash(patternLength)
        )
    }

    /**
     * 地图添加图片
     * @param anchorCenter 图片居中显示
     */
    fun addImageMarker(
        latLng: LatLng,
        imageTypeResId: Int,
        anchorCenter: Boolean = true,
        isDraggable: Boolean = false
    ): Marker? {
        ImageUtil.getBitmapFromDrawableAndSvg(mContext!!, imageTypeResId)?.apply {
            val newLatLng = toGCJ02LatLon(latLng)
            val imageTypeMarker =
                MarkerOptions().position(newLatLng).icon(BitmapDescriptorFactory.fromBitmap(this))
            imageTypeMarker.let {
                //图像上将置于标记的 LatLng 位置的点。该点默认为图像底部的中间位置。
                if (anchorCenter) it.anchor(it.anchorU, it.anchorV / 2)
                if (isDraggable) it.draggable(isDraggable)
            }
            return mGoogleMap?.addMarker(imageTypeMarker)
        }
        return null
    }

    fun addImageMarker(
        lat: Double,
        lon: Double,
        imageTypeResId: Int,
        anchorCenter: Boolean = true,
        isDraggable: Boolean = false
    ): Marker? {
        return addImageMarker(LatLng(lat, lon), imageTypeResId, anchorCenter, isDraggable)
    }

    /**
     * Adds a [Circle] around the provided
     * 地图上画一个圆形围栏
     *@param isDashedPattern 是否是虚线
     */
    fun addCircleFence(
        center: LatLng,
        radius: Double = 700.0,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
        isDashedPattern: Boolean = false
    ) {
        if (null == mGoogleMap) return

        val newLatLng = toGCJ02LatLon(center)
        val circleFence = mGoogleMap!!.addCircle(
            CircleOptions().center(newLatLng).radius(radius)
                .strokeWidth(AppUtils.dpToPx(1).toFloat()).fillColor(fillColor)
                .strokeColor(strokeColor)
        )

        if (isDashedPattern) {
            circleFence.strokePattern = getDashedPatternStyle()
        }

        if (null == mCircleFenceList) mCircleFenceList = mutableListOf()
        mCircleFenceList?.add(circleFence)
    }

    /**
     *
     * 地图上画一个圆形虚线围栏
     */
    fun addCircleImageFence(
        center: LatLng,
        radius: Double = 700.0,
        imageTypeResId: Int = 0,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
        isDashed: Boolean = true
    ) {
        if (imageTypeResId > 0) addImageMarker(center, imageTypeResId)
        addCircleFence(center, radius, strokeColor, fillColor, isDashed)
    }

    /**
     * 地图上画多边形
     * @param isDashedPattern 是否是虚线
     */
    private fun mapDrawPolygon(
        points: MutableList<LatLng>,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
        isDashedPattern: Boolean = false
    ) {
        mGoogleMap?.apply {
            val newLatLngList = if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
                val conLatLngList = mutableListOf<LatLng>()
                for (latLng in points) {
                    conLatLngList.add(toGCJ02LatLon(latLng))
                }
                conLatLngList
            } else {
                points
            }
            //构造PolygonOptions
            val polygonOptions =
                PolygonOptions().addAll(newLatLngList).strokeWidth(AppUtils.dpToPx(1).toFloat())
                    .fillColor(fillColor).strokeColor(strokeColor)

            if (isDashedPattern) {
                polygonOptions.strokePattern(getDashedPatternStyle())
            }

            val rectFence = addPolygon(polygonOptions)

            if (null == mPolygonFenceList) mPolygonFenceList = mutableListOf()
            mPolygonFenceList?.add(rectFence)
        }
    }

    /**
     * 地图上画一个矩形围栏
     */
    fun addRectFence(
        fencesBean: FencesBean,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
        isDashedPattern: Boolean = false
    ) {
        if (null == mGoogleMap) return

        val points = mutableListOf<LatLng>()
        fencesBean.apply {
            points.add(LatLng(latitudeA, longitudeA))
            points.add(LatLng(latitudeB, longitudeB))
            points.add(LatLng(latitudeC, longitudeC))
            points.add(LatLng(latitudeD, longitudeD))
        }
        mapDrawPolygon(points, strokeColor, fillColor, isDashedPattern)
    }

    /**
     *
     * 地图上画一个矩形虚线有中心图片围栏
     */
    fun addRectImageFence(
        fencesBean: FencesBean,
        imageTypeResId: Int = 0,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
        isDashedPattern: Boolean = true
    ) {
        if (imageTypeResId > 0) {
            addImageMarker(
                LatLng(fencesBean.latitudeCenter, fencesBean.longitudeCenter), imageTypeResId
            )
        }
        addRectFence(fencesBean, strokeColor, fillColor, isDashedPattern)
    }

    /**
     *
     * 地图上画一个正在预览的矩形虚线围栏
     */
    fun addRectImageEditFence(
        fencesBean: FencesBean, imageTypeResId: Int = 0,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
    ) {
        fencesBean.apply {
            addRectImageFence(this, imageTypeResId, strokeColor, fillColor)
            addImageMarker(LatLng(latitudeA, longitudeA), R.drawable.icon_fence_dot_svg)
            addImageMarker(LatLng(latitudeB, longitudeB), R.drawable.icon_fence_dot_svg)
            addImageMarker(LatLng(latitudeC, longitudeC), R.drawable.icon_fence_dot_svg)
            addImageMarker(LatLng(latitudeD, longitudeD), R.drawable.icon_fence_dot_svg)
        }
    }

    /**
     * 地图上画一个多边形围栏
     */
    fun addPolygonFence(
        fencesBean: FencesBean,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
        isDashedPattern: Boolean = false
    ) {
        if (null == mGoogleMap) return

        val points = mutableListOf<LatLng>()
        fencesBean.apply {
            points.add(LatLng(latitudeA, longitudeA))
            points.add(LatLng(latitudeB, longitudeB))
            points.add(LatLng(latitudeC, longitudeC))
            points.add(LatLng(latitudeD, longitudeD))
            points.add(LatLng(latitudeE, longitudeE))
            points.add(LatLng(latitudeF, longitudeF))
        }
        mapDrawPolygon(points, strokeColor, fillColor, isDashedPattern)
    }

    /**
     *
     * 地图上画一个多边形虚线有中心图片围栏
     */
    fun addPolygonImageFence(
        fencesBean: FencesBean,
        imageTypeResId: Int = 0,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
        isDashedPattern: Boolean = true
    ) {
        if (imageTypeResId > 0) addImageMarker(
            LatLng(
                fencesBean.latitudeCenter, fencesBean.longitudeCenter
            ), imageTypeResId
        )
        addPolygonFence(fencesBean, strokeColor, fillColor, isDashedPattern)
    }

    /**
     *
     * 地图上画一个正在预览的矩形虚线围栏
     */
    fun addPolygonImageEditFence(
        fencesBean: FencesBean, imageTypeResId: Int = 0,
        strokeColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color2),
        fillColor: Int = ContextCompat.getColor(mContext!!, R.color.select_color4),
    ) {
        fencesBean.apply {
            addPolygonImageFence(this, imageTypeResId, strokeColor, fillColor)
            addImageMarker(LatLng(latitudeA, longitudeA), R.drawable.icon_fence_polygon_operate_svg)
            addImageMarker(LatLng(latitudeB, longitudeB), R.drawable.icon_fence_polygon_operate_svg)
            addImageMarker(LatLng(latitudeC, longitudeC), R.drawable.icon_fence_polygon_operate_svg)
            addImageMarker(LatLng(latitudeD, longitudeD), R.drawable.icon_fence_polygon_operate_svg)
            addImageMarker(LatLng(latitudeE, longitudeE), R.drawable.icon_fence_polygon_operate_svg)
            addImageMarker(LatLng(latitudeF, longitudeF), R.drawable.icon_fence_polygon_operate_svg)
        }
    }

    /**
     * 清除地图有多个围栏圈
     */
    fun clearFenceList() {
//        if (null == mCircleFenceList) throw NullPointerException(
//            "mCircleList空指针,请在onMapLoadOk重写方法中实例化mCircleList,执行方法initFenceList()"
//        )
//        if (null == mRectFenceList) throw NullPointerException(
//            "mCircleList空指针,请在onMapLoadOk重写方法中实例化mCircleList,执行方法initFenceList()"
//        )
        mCircleFenceList?.forEach {
            it.remove()
        }
        mCircleFenceList?.clear()

        mPolygonFenceList?.forEach {
            it.remove()
        }
        mPolygonFenceList?.clear()
    }

    /**
     *  自动出现自定义头部地点布局,不需要点击
     */
    fun showMarkerInfoWindow(historyDataBean: HistoryDataBean) {
        mGoogleMap?.apply {
            mMarkerInfoWindowAdapter = MarkerInfoWindowAdapter(mContext!!)
            setInfoWindowAdapter(mMarkerInfoWindowAdapter)
            mMarker?.let {
                //传递位置信息给InfoWindowAdapter窗口
                it.tag = historyDataBean
                it.setInfoWindowAnchor(0.5f, 0f)
                it.showInfoWindow()
            }
        }
    }

    /**
     * 获取地图画线的PolylineOptions
     */
    fun getPolylineOptions(widthDp: Float, lineColorRes: Int): PolylineOptions {
        return PolylineOptions().clickable(false).width(AppUtils.dpToPx(widthDp))
            .color(ContextCompat.getColor(mContext!!, lineColorRes)).geodesic(false)
    }

    /**
     * 一次性画线 2条线叠加，黑黄叠加
     * 至少需要2个点的经纬度
     *  每画一次就清空之前画的
     */
    fun addSinglePolyline(googleMap: GoogleMap, latLngList: MutableList<LatLng>) {
        if (latLngList.size > 1) {
            val newLatLngList = if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
                val conLatLngList = mutableListOf<LatLng>()
                for (latLng in latLngList) {
                    conLatLngList.add(toGCJ02LatLon(latLng))
                }
                conLatLngList
            } else {
                latLngList
            }
            //先黄黑线
            getPolylineOptions(8f, R.color.line_stroke_color).let {
                it.addAll(newLatLngList)
                googleMap.addPolyline(it).apply {
                    startCap = RoundCap()
                    endCap = RoundCap()
                    //连接类型,可以指定棱台或圆角
                    jointType = JointType.ROUND
                }
            }

            //自定义描边图案
//        val pattern = listOf(Dot(), Gap(20F), Dash(30F), Gap(20F))
//        polyline.pattern = pattern

            //再画黄线
            getPolylineOptions(5f, R.color.rote_line_color).let {
                it.addAll(newLatLngList)
                googleMap.addPolyline(it).apply {
                    startCap = RoundCap()
                    endCap = RoundCap()
                    //连接类型,可以指定棱台或圆角
                    jointType = JointType.ROUND
                }
            }
        }
    }

    private var mYellowPolyline: Polyline? = null
    private var mBlackPolyline: Polyline? = null

    /**
     * 可以重复画线 2条线叠加，黑黄叠加
     * 需要1个点的经纬度
     * 每加个点就画一次
     */
    fun addPolyline(googleMap: GoogleMap, latLng: LatLng) {
        val newLatLng = toGCJ02LatLon(latLng)
        //先黑线
        if (null == mBlackPolyline) {
            getPolylineOptions(4f, R.color.white).let {
                it.add(newLatLng)
                mBlackPolyline = googleMap.addPolyline(it).apply {
                    endCap = RoundCap()
                    //连接类型,可以指定棱台或圆角
                    jointType = JointType.ROUND
                }
            }
        } else {
            val blackPoints = mBlackPolyline!!.points
            blackPoints.add(newLatLng)
            mBlackPolyline!!.points = blackPoints
        }

        //自定义描边图案
//        val pattern = listOf(Dot(), Gap(20F), Dash(30F), Gap(20F))
//        polyline.pattern = pattern
//        polyline.tag = "A"

        //再画黄线
        if (null == mYellowPolyline) {
            getPolylineOptions(3.5f, R.color.blue_color).let {
                it.add(newLatLng)
                mYellowPolyline = googleMap.addPolyline(it).apply {
                    //起点线帽图片,refWidth数值越小，图片越大
                    startCap = CustomCap(
                        BitmapDescriptorFactory.fromResource(R.drawable.map_live_start),
                        QMUIDisplayHelper.dpToPx(3).toFloat()
                    )
                    endCap = RoundCap()
                    jointType = JointType.ROUND
                }
            }
        } else {
            val yellowPoints = mYellowPolyline!!.points
            yellowPoints.add(newLatLng)
            mYellowPolyline!!.points = yellowPoints
        }

        LogUtil.e("点的个数：${mBlackPolyline?.points?.size},${mYellowPolyline?.points?.size}")
    }

    /**
     * 可以重复画线 2条线叠加，黑黄叠加
     * 需要1个点的经纬度
     * 每加个点就画一次
     */
//    fun addPolyLines(googleMap: GoogleMap, latLngList: MutableList<LatLng>) {
//        //先黑线
//        if (null == mBlackPolyline) {
//            getPolylineOptions(4f, R.color.txt_button).let {
//                it.addAll(latLngList)
//                mBlackPolyline = googleMap.addPolyline(it).apply {
//                    endCap = RoundCap()
//                    //连接类型,可以指定棱台或圆角
//                    jointType = JointType.ROUND
//                }
//            }
//        } else {
//            val blackPoints = mBlackPolyline!!.points
//            blackPoints.addAll(latLngList)
//            mBlackPolyline!!.points = blackPoints
//        }
//
//        //再画黄线
//        if (null == mYellowPolyline) {
//            getPolylineOptions(3.5f, R.color.btn_yellow_color).let {
//                it.addAll(latLngList)
//                mYellowPolyline = googleMap.addPolyline(it).apply {
//                    //起点线帽图片,refWidth数值越小，图片越大
//                    startCap = CustomCap(
//                        BitmapDescriptorFactory.fromResource(R.drawable.map_live_start),
//                        QMUIDisplayHelper.dpToPx(3).toFloat()
//                    )
//                    endCap = RoundCap()
//                    jointType = JointType.ROUND
//                }
//            }
//        } else {
//            val yellowPoints = mYellowPolyline!!.points
//            yellowPoints.addAll(latLngList)
//            mYellowPolyline!!.points = yellowPoints
//        }
//        LogUtil.e("点的个数：${mBlackPolyline?.points?.size},${mYellowPolyline?.points?.size}")
//    }

    override fun onMapReady(googleMap: GoogleMap) {
        LogUtil.e("谷歌地图加载好了")
        mGoogleMap = googleMap

        isMapLoadOk = true

//        googleMap.uiSettings.apply {
//            //右下角工具栏不显示
//            isMapToolbarEnabled = true
//            //指南针
//            isCompassEnabled = true
//            //定位按钮
//            isMyLocationButtonEnabled = true
//        }

        //地图样式
        setGoogleMapType()

        googleMap.apply {
            //显示实时交通信息
//            isTrafficEnabled = true
            //检测权限，开启用户的当前位置https://developers.google.cn/maps/documentation/android-sdk/location?hl=zh-cn
            if (ActivityCompat.checkSelfPermission(
                    mContext!!, Manifest.permission.ACCESS_FINE_LOCATION
                ) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                    mContext!!, Manifest.permission.ACCESS_COARSE_LOCATION
                ) == PackageManager.PERMISSION_GRANTED
            ) {
                //启用“我的位置”图层。
                isMyLocationEnabled = true
            }
            uiSettings.let {
                //禁止显示“我的位置”按钮。
                it.isMyLocationButtonEnabled = false
                //用于设置是启用还是停用倾斜手势的偏好设置。
                // https://developers.google.cn/maps/documentation/android-sdk/reference/com/google/android/libraries/maps/UiSettings?hl=zh-cn
                it.isMapToolbarEnabled = false
                it.isTiltGesturesEnabled = false
                it.isCompassEnabled = true
            }

            onMapLoadOk(googleMap)
        }
    }

    //*************************定位代码start****************************************

    // The Fused Location Provider provides access to location APIs.
    private val mFusedLocationClient: FusedLocationProviderClient by lazy {
        LocationServices.getFusedLocationProviderClient(mContext!!)
    }
    private var mCancellationTokenSource: CancellationTokenSource? = null


    /**
     * 获取最后位置,用户当前的位置
     */
    @SuppressLint("MissingPermission")
    fun getLastLocation() {
        mFusedLocationClient.lastLocation.addOnCompleteListener { taskLocation ->
            var location: Location? = null
            if (taskLocation.isSuccessful && taskLocation.result != null) {
                location = taskLocation.result
                LonAndLatUtil.currentUserGPSLat = location.latitude
                LonAndLatUtil.currentUserGPSLon = location.longitude
                LogUtil.e("getLastLocation：${location.latitude}, ${location.longitude}")
            } else {
                LogUtil.e("getLastLocation:exception" + taskLocation.exception)
            }
            if (null != location) {
                mUserLatLng = LatLng(location.latitude, location.longitude)
                if (isLocationSuccessCallback) {
                    setUserMarker()
                    locationSuccess(location)
                }
                isLocationSuccessCallback = false
            } else requestCurrentLocation()
        }

    }

    /**
     * 请求用户当前的位置
     */
    @SuppressLint("MissingPermission")
    fun requestCurrentLocation() {
        try {
            if (null == mCancellationTokenSource) mCancellationTokenSource =
                CancellationTokenSource()
//        val currentLocationTask = mFusedLocationClient.getCurrentLocation(
//            LocationRequest.PRIORITY_HIGH_ACCURACY, mCancellationTokenSource!!.token
//        )
            val currentLocationTask = mFusedLocationClient.getCurrentLocation(
                Priority.PRIORITY_HIGH_ACCURACY, mCancellationTokenSource!!.token
            )
            currentLocationTask.addOnCompleteListener { task: Task<Location> ->
                var location: Location? = null
                val result = if (task.isSuccessful && task.result != null) {
                    location = task.result
                    LonAndLatUtil.currentUserGPSLat = location.latitude
                    LonAndLatUtil.currentUserGPSLon = location.longitude
                    "(success): ${location.latitude}, ${location.longitude}"
                } else {
                    val exception = task.exception
                    "(failure): $exception"
                }

                LogUtil.e("requestCurrentLocation $result")
                if (null != location) {
                    mUserLatLng = LatLng(location.latitude, location.longitude)
                    if (isLocationSuccessCallback) locationSuccess(location)
                    isLocationSuccessCallback = false
                }
            }
        } catch (e: Exception) {
            LogUtil.e("requestCurrentLocation异常:${e.message}")
        }
    }

    //*************************定位代码end****************************************

    /**
     * 由 points 组成的区域 距离手机屏幕距离screenPaddingPx 像素单位
     */
    fun setLatLngZoom(context: Context, screenPaddingPx: Int, vararg points: LatLng) {
//        val width = context.resources.displayMetrics.widthPixels
//        val height = context.resources.displayMetrics.heightPixels
//        val padding = width / 8
        val builder = LatLngBounds.Builder()
        for (item in points) {
            builder.include(toGCJ02LatLon(item))
        }
        //根据经纬度来设置缩放级别
//        mCameraUpdate = CameraUpdateFactory.newLatLngBounds(
//            builder.build(), width, (height / 2.5f).toInt(), padding.toInt()
//        )
        mCameraUpdate = CameraUpdateFactory.newLatLngBounds(builder.build(), screenPaddingPx)
    }

    private fun cameraUpdateMove() {
        mGoogleMap?.apply {
            mCameraUpdate?.let {
                animateCamera(it)
            }
        }
    }

    fun getMyZoom1(distance: Double): Float {
        val scale = intArrayOf(
            3,//21
            5,//20
            10,//19
            30,//18
            50,//17
            90,//16
            200,//15
            400,//14
            800,//13
            1400,//12
            2900,//11
            5800,//10
            11000,//9
            22000,//8
            43000,//7
            88000,//6
            170000,//5
            330000,//4
            390000,//3
            1530000,//2级缩放
        )
        var jl = distance
        if (distance < 3) {
            jl = 4.0
        }
        LogUtil.e("最大和最小间经纬度直线距离 = $jl")
        var i = 0
        while (i < scale.size - 2) {
            if (scale[i] < jl && scale[i + 1] >= jl) {
                break
            }
            i++
        }
        LogUtil.e("根据距离获取Zoom=${21f - i}")
        return 21f - i
    }

    /**
     * 根据显示距离获取缩放地图等级
     */
    fun getDistanceZoom(distance: Double): Float {
        val scale = intArrayOf(
            10,//21
            30,//20
            50,//19
            80,//18
            100,//17
            400,//16
            800,//15
            1000,//14
            2000,//13
            3000,//12
            4000,//11
            58000,//10
            11000,//9
            22000,//8
            44000,//7
            88000,//6
            170000,//5
            330000,//4
            1000000,//3
            1530000,//2级缩放
        )
        LogUtil.e("最大和最小间经纬度直线距离 = $distance")
        val zoom: Float = if (distance <= scale[0]) {
            21f
        } else if (distance >= scale[scale.size - 1]) {
            1f
        } else {
            var i = 0
            while (i < scale.size - 2) {
                if (scale[i] < distance && scale[i + 1] >= distance) {
                    break
                }
                i++
            }
            21f - i
        }
        LogUtil.e("根据距离获取Zoom=$zoom")
        return zoom
    }

    /**
     * 设置Marker弹窗消息的位置
     */
    fun setMarkerInfoViewOffset(markerInfoView: MapMarkerInfoView, latLng: LatLng) {
        val newLatLng = toGCJ02LatLon(latLng)
        mGoogleMap?.projection?.toScreenLocation(newLatLng)?.let {
            ViewUtil.instance.viewShow(markerInfoView)
            markerInfoView.setOffsetXY(it.x, it.y - AppUtils.dpToPx(56))
        }
    }

    /**
     * 设置Marker弹窗设备电量的位置
     */
    fun setMapDeviceBatteryOffset(
        viewGroup: ViewGroup, latLng: LatLng, mapDeviceBean: MapDeviceBean
    ) {
        val newLatLng = toGCJ02LatLon(latLng)
        mGoogleMap?.projection?.toScreenLocation(newLatLng)?.let {
            viewGroup.x = it.x.toFloat() - viewGroup.width / 2 + AppUtils.dpToPx(5)
            viewGroup.y = it.y.toFloat() - AppUtils.dpToPx(56) - viewGroup.height
            if (mapDeviceBean.canShowBattery && !mapDeviceBean.isCloseBattery) ViewUtil.instance.viewShow(
                viewGroup
            )
        }
    }

    /**
     * 设置地图网络类型显示位置
     */
    fun setMapNetTypeViewOffset(mapDeviceNetView: MapDeviceNetView, latLng: LatLng) {
        mGoogleMap?.projection?.toScreenLocation(latLng)?.let {
            mapDeviceNetView.visibility = View.VISIBLE
            mapDeviceNetView.setOffsetXY(it.x + AppUtils.dpToPx(11), it.y - AppUtils.dpToPx(56))
        }
    }

    /**
     * 转换国内火星坐标
     */
    fun toGCJ02LatLon(latLng: LatLng): LatLng {
        return if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
            val convertLatLon =
                LonAndLatUtil.convertFromWGS84ToGCJ02(latLng.latitude, latLng.longitude)
            LatLng(convertLatLon[0], convertLatLon[1])
        } else {
            latLng
        }
    }

    /**
     * 转换GPS坐标
     */
    fun toGpsLatLon(latLng: LatLng): LatLng {
        return if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
            val convertLatLon = LonAndLatUtil.convertFromGCJ02ToWGS84(
                latLng.latitude, latLng.longitude
            )
            LatLng(convertLatLon[0], convertLatLon[1])
        } else latLng
    }

    /**
     * 定位成功返回
     */
    open fun locationSuccess(location: Location?) {}

    /**
     * 地图加载完毕
     */
    abstract fun onMapLoadOk(googleMap: GoogleMap)

    /**
     * 宠物位置刷新完成
     */
    open fun onRefreshPetCurrentLocationOk(googleMap: GoogleMap) {
    }

    override fun onStop() {
        super.onStop()
        mCancellationTokenSource?.cancel()
        mGoogleMapView?.onStop()
    }

    override fun onDestroy() {
        super.onDestroy()
        mPetHeadIconBitmap?.recycle()
        mGoogleMapView?.onDestroy()
    }
}

