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.baselibrary.util.Utils
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()
                }
            }

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

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

            setOnMapLongClickListener {
                resetFencesViewCentre(it)
                mapOkAndDistancePointLatLng(0)
            }
        }

        getLastLocation()

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

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

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

            return
        }

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

    /**
     * 重新设置围栏控件的中心点位置
     */
    fun resetFencesViewCentre(centreLatLng: LatLng) {
        mGoogleMap?.projection?.toScreenLocation(centreLatLng)?.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 = 1000) {
        if (mFencesBean.startDrag) return
        if (delayMillis == 0L) {
            val arrayOfDistance = getLatLngAndCalDistance()
            if (mFencesBean.startDrag) return
            mOnActivityCallBack?.calculationDistance(arrayOfDistance)
        } else {
            //延时计算距离，防止围栏没画好/地图摄像头移动中
            mFencesCircleView.postDelayed({
                val arrayOfDistance = getLatLngAndCalDistance()
                mOnActivityCallBack?.calculationDistance(arrayOfDistance)
            }, delayMillis)
        }
    }

    private fun getLatLngAndCalDistance(): Array<String> {
        // 经纬度转换为手机坐标点
//            val x = mGoogleMap!!.projection.toScreenLocation(it).x
        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
                )
                mFencesBean.apply {
                    latitudeCenter = centreLatLng.latitude
                    longitudeCenter = centreLatLng.longitude
                    ancillaryLatitude = endLatLng.latitude
                    ancillaryLongitude = endLatLng.longitude
                    ancillaryOtherLatitude = startLatLng.latitude
                    ancillaryOtherLongitude = startLatLng.longitude
                }
                arrayOf(
                    Utils.formatDecimal(distance, 2)
                )
            }

            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
                )
                mFencesBean.apply {
                    latitudeCenter = centreLatLng.latitude
                    longitudeCenter = centreLatLng.longitude
                    latitudeA = rectALatLng.latitude
                    longitudeA = rectALatLng.longitude
                    latitudeB = rectBLatLng.latitude
                    longitudeB = rectBLatLng.longitude
                    latitudeC = rectCLatLng.latitude
                    longitudeC = rectCLatLng.longitude
                    latitudeD = rectDLatLng.latitude
                    longitudeD = rectDLatLng.longitude
                }
                //长度和高度
                arrayOf(
                    Utils.formatDecimal(rectWidthDistance, 2),
                    Utils.formatDecimal(rectHeightDistance, 2)
                )
            }

            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 {
                    latitudeCenter = centreLatLng.latitude
                    longitudeCenter = centreLatLng.longitude
                    latitudeA = polygonALatLng.latitude
                    longitudeA = polygonALatLng.longitude
                    latitudeB = polygonBLatLng.latitude
                    longitudeB = polygonBLatLng.longitude
                    latitudeC = polygonCLatLng.latitude
                    longitudeC = polygonCLatLng.longitude
                    latitudeD = polygonDLatLng.latitude
                    longitudeD = polygonDLatLng.longitude
                    latitudeE = polygonELatLng.latitude
                    longitudeE = polygonELatLng.longitude
                    latitudeF = polygonFLatLng.latitude
                    longitudeF = polygonFLatLng.longitude
                }
                //多边形，不需要计算距离
                arrayOf("0")
            }
        }
    }

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

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

                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 = mGoogleMap!!.projection.toScreenLocation(
                    LatLng(latitudeCenter, longitudeCenter)
                )
                val pointLineEnd = mGoogleMap!!.projection.toScreenLocation(
                    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 = mGoogleMap!!.projection.toScreenLocation(
                    LatLng(latitudeCenter, longitudeCenter)
                )
                val pointA = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeA, longitudeA))
                val pointB = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeB, longitudeB))
                val pointC = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeC, longitudeC))
                val pointD = mGoogleMap!!.projection.toScreenLocation(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 = mGoogleMap!!.projection.toScreenLocation(
                    LatLng(latitudeCenter, longitudeCenter)
                )
                val pointA = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeA, longitudeA))
                val pointB = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeB, longitudeB))
                val pointC = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeC, longitudeC))
                val pointD = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeD, longitudeD))
                val pointE = mGoogleMap!!.projection.toScreenLocation(LatLng(latitudeE, longitudeE))
                val pointF = mGoogleMap!!.projection.toScreenLocation(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
    }
}