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

import android.content.Context
import android.graphics.Point
import android.location.Location
import android.view.View
import androidx.core.view.isVisible
import com.abbidot.baselibrary.util.LogUtil
import com.abbidot.tracker.bean.FencesBean
import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.ui.common.map.FencesAddEditMapCommon
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.widget.FencesCircleView
import com.abbidot.tracker.widget.FencesPolygonView
import com.abbidot.tracker.widget.FencesRectView
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.LatLng
import kotlin.math.abs
import kotlin.math.pow

/**
 *Created  by .yzq on 2024/4/23/023.
 * @link
 * @description:
 */
class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {

    private lateinit var mFencesBean: FencesBean
    private var isEditFences = false
    private lateinit var mFencesCircleView: FencesCircleView
    private lateinit var mFencesRectView: FencesRectView
    private lateinit var mFencesPolygonView: FencesPolygonView
    private var mOnActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack? = null

    private lateinit var mMapLoadOk: () -> Unit

    //防止刚开始移动摄像头有时会执行2次
    private var isCanExecuteCameraCallBack = false

    //防止地图摄像头移动动画自动设置地图缩放级别,会执行setOnCameraMoveListener()
    private var isMapZoomReady = false

    companion object {
        @JvmStatic
        fun newInstance(
            context: Context,
            fencesBean: FencesBean,
            fencesCircleView: FencesCircleView,
            fencesRectView: FencesRectView,
            fencesPolygonView: FencesPolygonView,
            isEdit: Boolean,
            onActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack?,
            mapLoadOk: () -> Unit
        ) = FencesAddEditGoogleMapFragment().apply {
            mContext = context
            mFencesBean = fencesBean
            isEditFences = isEdit
            mFencesCircleView = fencesCircleView
            mFencesRectView = fencesRectView
            mFencesPolygonView = fencesPolygonView
            mOnActivityCallBack = onActivityCallBack
            mMapLoadOk = mapLoadOk
        }
    }

    override fun onMapLoadOk(googleMap: GoogleMap) {
        //监听摄像机移动中心点,摄像机移动结束时的回调接口。有时会执行2次
        mGoogleMap?.apply {
            setOnCameraIdleListener {
                if (isCanExecuteCameraCallBack) {
                    //现在围栏控件改成随地图移动，只需要执行一次
                    isCanExecuteCameraCallBack = false
                    mapOkAndDistancePointLatLng(500)
                    setScaleLimitDistance()
                }
            }

            setOnCameraMoveListener {
                mFencesBean.let {
                    val latLng = LatLng(it.latitudeCenter, it.longitudeCenter)
                    resetFencesViewCentre(latLng)
                }

                //监听地图放大缩小操作
                if (isMapZoomReady && getGoogleMapZoom() != cameraPosition.zoom) {
                    setGoogleMapZoom(cameraPosition.zoom)
                    resetFencesViewSize()
                    setScaleLimitDistance()
                }
            }

            setOnMapLongClickListener {
                toGpsLatLon(it).let { n ->
                    mFencesBean.let { f ->
                        f.latitudeCenter = n.latitude
                        f.longitudeCenter = n.longitude
                    }
                    resetFencesViewCentre(n)
                }
            }
        }

        getLastLocation()

        //变量是否初始化
        if (::mMapLoadOk.isInitialized) mMapLoadOk()
    }

    override fun locationSuccess(location: Location?) {
        if (isEditFences) {
            mFencesBean.apply {
                moveCameraUpdate(latitudeCenter, longitudeCenter)
            }

            //延时执行，防止围栏没画好/地图摄像头移动中
            mFencesCircleView.postDelayed({
                isMapZoomReady = true
                restoreEditFences()
            }, 500)
            return
        }

        isMapZoomReady = true
        location?.apply {
            mFencesBean.latitudeCenter = latitude
            mFencesBean.longitudeCenter = longitude
            isCanExecuteCameraCallBack = true
            moveCameraLocation(LatLng(latitude, longitude), false)
        }
    }

    /**
     * 重新设置围栏控件的中心点位置
     */
    fun resetFencesViewCentre(centreLatLng: LatLng) {
        val newLatLng = toGCJ02LatLon(centreLatLng)
        mGoogleMap?.projection?.toScreenLocation(newLatLng)?.apply {
            mFencesCircleView.setCentreXY(this)
            mFencesRectView.setCentreXY(this)
            mFencesPolygonView.setCentreXY(this)
        }
    }

    /**
     * 重新设置围栏控件的大小
     */
    private fun resetFencesViewSize() {
        if (mFencesCircleView.isVisible) {
            if (mFencesBean.radius <= 0.0) return
            restoreCircleFences()
        } else if (mFencesRectView.isVisible) {
            restoreRectFences()
        } else if (mFencesPolygonView.isVisible) {
            restorePolygonFences()
        }
    }

    /**
     * 地图准备好计算距离
     */
    fun mapOkAndDistancePointLatLng(delayMillis: Long) {
        if (mFencesBean.startDrag) return
        if (delayMillis == 0L) {
            val arrayOfDistance = getLatLngAndCalDistance()
            mOnActivityCallBack?.calculationDistance(arrayOfDistance)
        } else {
            //延时计算距离，防止围栏没画好/地图摄像头移动中
            mFencesCircleView.postDelayed({
                val arrayOfDistance = getLatLngAndCalDistance()
                mOnActivityCallBack?.calculationDistance(arrayOfDistance)
            }, delayMillis)
        }
    }

    /**
     * 设置围栏最小可拖动距离
     */
    private fun setScaleLimitDistance() {
        mGoogleMap?.apply {
            //假设取个离(100,100)x坐标100的点
            var stepX: Int
            var stepY: Int
            //手机坐标点转换为经纬度
            val centreLatLng = Point(100, 100).let {
                stepX = it.x + 100
                stepY = it.y
                projection.fromScreenLocation(it)
            }
            val stepLatLng = projection.fromScreenLocation(Point(stepX, stepY))
            val stepDistance = Util.measureLatLonDistance(
                centreLatLng.latitude,
                centreLatLng.longitude,
                stepLatLng.latitude,
                stepLatLng.longitude
            )
            //限制圆半径50m
            val limitRadius = 100 / stepDistance * 50
            //限制矩形边长100m
            val limitSide = 100 / stepDistance * 100
            LogUtil.e("setScaleLimitDistance,$stepDistance,$limitRadius,$limitSide,${cameraPosition.zoom}")
            mFencesCircleView.mLimitRadius = limitRadius.toFloat()
            mFencesRectView.mLimitSide = limitSide.toFloat()
            mFencesPolygonView.mLimitSide = limitSide.toFloat()
        }
    }

    private fun getLatLngAndCalDistance(): Array<String> {
        if (null == mGoogleMap) return arrayOf("0", "0")

        return when (mFencesBean.fenceShapeType) {
            ConstantInt.CircleShapeType -> {
                //手机坐标点转换为经纬度
                val centreLatLng = mFencesCircleView.getCircleCentrePoint().let {
                    mGoogleMap!!.projection.fromScreenLocation(it)
                }
                val startLatLng = mFencesCircleView.getCircleLineStartPoint().let {
                    mGoogleMap!!.projection.fromScreenLocation(it)
                }
                val endLatLng = mFencesCircleView.getCircleLineEndPoint()
                    .let { mGoogleMap!!.projection.fromScreenLocation(it) }
                LogUtil.e("GoogleMap,setOnCameraIdleListener 监听回调")
//                LogUtil.e("startLatLng=$centreLatLng,endLatLng=$endLatLng")
                val distance = Util.measureLatLonDistance(
                    centreLatLng.latitude,
                    centreLatLng.longitude,
                    endLatLng.latitude,
                    endLatLng.longitude
                )
                val distanceInt = distance.toInt()
                val showDistance = getShowDistance(distanceInt)
                LogUtil.e("getLatLngAndCalDistance,$distanceInt,$showDistance")
                mFencesBean.apply {
                    toGpsLatLon(centreLatLng).let {
                        latitudeCenter = it.latitude
                        longitudeCenter = it.longitude
                    }
                    toGpsLatLon(endLatLng).let {
                        ancillaryLatitude = it.latitude
                        ancillaryLongitude = it.longitude
                    }
                    toGpsLatLon(startLatLng).let {
                        ancillaryOtherLatitude = it.latitude
                        ancillaryOtherLongitude = it.longitude
                    }
                }
                arrayOf(
                    distanceInt.toString(), showDistance.toString()
                )
            }

            ConstantInt.RectangleShapeType -> {
                val centreLatLng = mFencesRectView.getRectCentrePoint()
                    .let { mGoogleMap!!.projection.fromScreenLocation(it) }
                val rectALatLng = mFencesRectView.getRectABCDPoint(FencesPolygonView.POINT_A).let {
                    mGoogleMap!!.projection.fromScreenLocation(it)
                }
                val rectBLatLng = mFencesRectView.getRectABCDPoint(FencesPolygonView.POINT_B).let {
                    mGoogleMap!!.projection.fromScreenLocation(it)
                }
                val rectCLatLng = mFencesRectView.getRectABCDPoint(FencesPolygonView.POINT_C).let {
                    mGoogleMap!!.projection.fromScreenLocation(it)
                }
                val rectDLatLng = mFencesRectView.getRectABCDPoint(FencesPolygonView.POINT_D).let {
                    mGoogleMap!!.projection.fromScreenLocation(it)
                }
                val rectWidthDistance = Util.measureLatLonDistance(
                    rectALatLng.latitude,
                    rectALatLng.longitude,
                    rectBLatLng.latitude,
                    rectBLatLng.longitude
                )
                val rectHeightDistance = Util.measureLatLonDistance(
                    rectBLatLng.latitude,
                    rectBLatLng.longitude,
                    rectCLatLng.latitude,
                    rectCLatLng.longitude
                )
                val widthDistance = rectWidthDistance.toInt()
                val showWidthDistance = getShowDistance(widthDistance)
                val heightDistance = rectHeightDistance.toInt()
                val showHeightDistance = getShowDistance(heightDistance)
                mFencesBean.apply {
                    toGpsLatLon(centreLatLng).let {
                        latitudeCenter = it.latitude
                        longitudeCenter = it.longitude
                    }
                    toGpsLatLon(rectALatLng).let {
                        latitudeA = it.latitude
                        longitudeA = it.longitude
                    }
                    toGpsLatLon(rectBLatLng).let {
                        latitudeB = it.latitude
                        longitudeB = it.longitude
                    }
                    toGpsLatLon(rectCLatLng).let {
                        latitudeC = it.latitude
                        longitudeC = it.longitude
                    }
                    toGpsLatLon(rectDLatLng).let {
                        latitudeD = it.latitude
                        longitudeD = it.longitude
                    }
                }
                //长度和高度
                arrayOf(
                    widthDistance.toString(),
                    heightDistance.toString(),
                    showWidthDistance.toString(),
                    showHeightDistance.toString()
                )
            }

            else -> {
                val centreLatLng = mFencesPolygonView.getPolygonCentrePoint().let {
                    mGoogleMap!!.projection.fromScreenLocation(it)
                }
                val polygonALatLng =
                    mFencesPolygonView.getPolygonABCDEFPoint(FencesPolygonView.POINT_A).let {
                        mGoogleMap!!.projection.fromScreenLocation(it)
                    }
                val polygonBLatLng =
                    mFencesPolygonView.getPolygonABCDEFPoint(FencesPolygonView.POINT_B).let {
                        mGoogleMap!!.projection.fromScreenLocation(it)
                    }
                val polygonCLatLng =
                    mFencesPolygonView.getPolygonABCDEFPoint(FencesPolygonView.POINT_C).let {
                        mGoogleMap!!.projection.fromScreenLocation(it)
                    }
                val polygonDLatLng =
                    mFencesPolygonView.getPolygonABCDEFPoint(FencesPolygonView.POINT_D).let {
                        mGoogleMap!!.projection.fromScreenLocation(it)
                    }
                val polygonELatLng =
                    mFencesPolygonView.getPolygonABCDEFPoint(FencesPolygonView.POINT_E).let {
                        mGoogleMap!!.projection.fromScreenLocation(it)
                    }
                val polygonFLatLng =
                    mFencesPolygonView.getPolygonABCDEFPoint(FencesPolygonView.POINT_F).let {
                        mGoogleMap!!.projection.fromScreenLocation(it)
                    }
                mFencesBean.apply {
                    toGpsLatLon(centreLatLng).let {
                        latitudeCenter = it.latitude
                        longitudeCenter = it.longitude
                    }
                    toGpsLatLon(polygonALatLng).let {
                        latitudeA = it.latitude
                        longitudeA = it.longitude
                    }
                    toGpsLatLon(polygonBLatLng).let {
                        latitudeB = it.latitude
                        longitudeB = it.longitude
                    }
                    toGpsLatLon(polygonCLatLng).let {
                        latitudeC = it.latitude
                        longitudeC = it.longitude
                    }
                    toGpsLatLon(polygonDLatLng).let {
                        latitudeD = it.latitude
                        longitudeD = it.longitude
                    }
                    toGpsLatLon(polygonELatLng).let {
                        latitudeE = it.latitude
                        longitudeE = it.longitude
                    }
                    toGpsLatLon(polygonFLatLng).let {
                        latitudeF = it.latitude
                        longitudeF = it.longitude
                    }
                }
                //多边形，不需要计算距离
                arrayOf("0")
            }
        }
    }

    /**
     * 获取ui显示的距离，经过算法处理的
     */
    private fun getShowDistance(distance: Int): Int {
        val singleDigit = distance % 10
        val integerDigit = distance / 10 * 10
        return if (singleDigit > 4) integerDigit + 10
        else integerDigit
    }

    /**
     * 还原围栏
     */
    private fun restoreEditFences() {
        var arrayOfDistance = arrayOf("0")
        setScaleLimitDistance()
        mFencesBean.apply {
            when (mFencesBean.fenceShapeType) {
                ConstantInt.CircleShapeType -> {
                    restoreCircleFences()
                    val showDistance = getShowDistance(radius)
                    arrayOfDistance = arrayOf("$radius", "$showDistance")
                }

                ConstantInt.RectangleShapeType -> {
                    restoreRectFences()
                    val showWidthDistance = getShowDistance(longDistance)
                    val showHeightDistance = getShowDistance(shortDistance)
                    arrayOfDistance = arrayOf(
                        "$longDistance",
                        "$shortDistance",
                        "$showWidthDistance",
                        "$showHeightDistance"
                    )
                }

                ConstantInt.PolygonShapeType -> {
                    restorePolygonFences()
                    arrayOfDistance = arrayOf("0")
                }
            }

            mOnActivityCallBack?.calculationDistance(arrayOfDistance)
        }
        isCanExecuteCameraCallBack = true
    }

    /**
     * 还原圆形围栏
     */
    private fun restoreCircleFences() {
        if (null == mGoogleMap) return
        mFencesBean.apply {
            mFencesCircleView.let {
                it.visibility = View.VISIBLE
                val pointCentre = latLngToScreenLocation(
                    LatLng(latitudeCenter, longitudeCenter)
                )
                val pointLineEnd = latLngToScreenLocation(
                    LatLng(ancillaryLatitude, ancillaryLongitude)
                )
                val radius = abs(pointLineEnd.x - pointCentre.x).toFloat()
                it.setCircleRadiusPx(radius)

                //圆形大小变了,其他形状的围栏也要改变大小
                val rectA = Point(
                    (pointLineEnd.x - radius * 2).toInt(), (pointLineEnd.y - radius).toInt()
                )
                val rectB = Point(pointLineEnd.x, (pointLineEnd.y - radius).toInt())
                val rectC = Point(pointLineEnd.x, (pointLineEnd.y + radius).toInt())
                val rectD =
                    Point((pointLineEnd.x - radius * 2).toInt(), (pointLineEnd.y + radius).toInt())
                mFencesRectView.setRectABCDXYPoint(pointCentre, rectA, rectB, rectC, rectD)
                val polygonA = Point(pointCentre.x, (pointCentre.y - radius).toInt())
                val polygonB = Point(pointLineEnd.x, (pointLineEnd.y - radius / 2).toInt())
                val polygonC = Point(pointLineEnd.x, (pointLineEnd.y + radius / 2).toInt())
                val polygonD = Point(pointCentre.x, (pointCentre.y + radius).toInt())
                val polygonE = Point(
                    (pointLineEnd.x - 2 * radius).toInt(), (pointLineEnd.y + radius / 2).toInt()
                )
                val polygonF = Point(
                    (pointLineEnd.x - 2 * radius).toInt(), (pointLineEnd.y - radius / 2).toInt()
                )
                mFencesPolygonView.setPolygonABCDEFPoint(
                    pointCentre, polygonA, polygonB, polygonC, polygonD, polygonE, polygonF
                )
            }
        }
    }

    /**
     * 还原矩形围栏大小
     */
    private fun restoreRectFences() {
        if (null == mGoogleMap) return
        mFencesBean.apply {
            mFencesRectView.let {
                it.visibility = View.VISIBLE
                val pointCentre = latLngToScreenLocation(
                    LatLng(latitudeCenter, longitudeCenter)
                )
                val pointA = latLngToScreenLocation(LatLng(latitudeA, longitudeA))
                val pointB = latLngToScreenLocation(LatLng(latitudeB, longitudeB))
                val pointC = latLngToScreenLocation(LatLng(latitudeC, longitudeC))
                val pointD = latLngToScreenLocation(LatLng(latitudeD, longitudeD))
                it.setRectABCDXYPoint(pointCentre, pointA, pointB, pointC, pointD)

                //矩形大小变了,其他形状的围栏也要改变大小
                val radius = abs(pointA.x - pointCentre.x).toFloat()
                mFencesCircleView.setCircleRadiusPx(radius)
                val minX = minOf(pointA.x, pointB.x, pointC.x, pointD.x)
                val maxX = maxOf(pointA.x, pointB.x, pointC.x, pointD.x)
                val minY = minOf(pointA.y, pointB.y, pointC.y, pointD.y)
                val maxY = maxOf(pointA.y, pointB.y, pointC.y, pointD.y)
                val difX = maxX - minX
                val difY = maxY - minY
                val polygonA = Point(minX + difX / 2, minY)
                val polygonB = Point(maxX, minY + difY / 4)
                val polygonC = Point(maxX, maxY - difY / 4)
                val polygonD = Point(minX + difX / 2, maxY)
                val polygonE = Point(minX, maxY - difY / 4)
                val polygonF = Point(minX, minY + difY / 4)
                mFencesPolygonView.setPolygonABCDEFPoint(
                    pointCentre, polygonA, polygonB, polygonC, polygonD, polygonE, polygonF
                )
            }
        }
    }

    /**
     * 还原多边形围栏大小
     */
    private fun restorePolygonFences() {
        if (null == mGoogleMap) return
        mFencesBean.apply {
            mFencesPolygonView.let {
                it.visibility = View.VISIBLE
                val pointCentre = latLngToScreenLocation(
                    LatLng(latitudeCenter, longitudeCenter)
                )
                val pointA = latLngToScreenLocation(LatLng(latitudeA, longitudeA))
                val pointB = latLngToScreenLocation(LatLng(latitudeB, longitudeB))
                val pointC = latLngToScreenLocation(LatLng(latitudeC, longitudeC))
                val pointD = latLngToScreenLocation(LatLng(latitudeD, longitudeD))
                val pointE = latLngToScreenLocation(LatLng(latitudeE, longitudeE))
                val pointF = latLngToScreenLocation(LatLng(latitudeF, longitudeF))
                it.setPolygonABCDEFPoint(
                    pointCentre, pointA, pointB, pointC, pointD, pointE, pointF
                )

                val maxX = maxOf(pointA.x, pointB.x, pointC.x, pointD.x, pointE.x, pointF.x)
                //多边形大小变了,其他形状的围栏也要改变大小
                val radius = abs(maxX - pointCentre.x).toFloat()
                mFencesCircleView.setCircleRadiusPx(radius)
                val minX = minOf(pointA.x, pointB.x, pointC.x, pointD.x, pointE.x, pointF.x)
                val minY = minOf(pointA.y, pointB.y, pointC.y, pointD.y, pointE.y, pointF.y)
                val maxY = maxOf(pointA.y, pointB.y, pointC.y, pointD.y, pointE.y, pointF.y)
                val rectA = Point(minX, minY)
                val rectB = Point(maxX, minY)
                val rectC = Point(maxX, maxY)
                val rectD = Point(minX, maxY)
                mFencesRectView.setRectABCDXYPoint(pointCentre, rectA, rectB, rectC, rectD)
            }
        }
    }

    /**
     * 根据地图显示级别,计算比例尺的一像素对应几米
     */
    private fun getCircleRadiusPx(distanceRadius: Double): Double {
        val zoom = getDistanceZoom(distanceRadius)
        //一像素对应几米
        val pxDis = 2.0.pow(15.5 - zoom)
        //计算现在半径有多少像素
        return distanceRadius / pxDis
    }

    /**
     * 根据地图显示级别,计算比例尺的一像素对应几米
     */
    private fun zoomToCircleRadiusPx(distanceRadius: Double): Double {
        val zoom = getGoogleMapZoom()
        //一像素对应几米
        val pxDis = 2.0.pow(15.5 - zoom)
        //计算现在半径有多少像素
        return distanceRadius / pxDis
    }
}