package com.base.locationsharewhite.ui.locationmap

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.animation.LinearInterpolator
import androidx.activity.addCallback
import androidx.core.location.LocationManagerCompat.requestLocationUpdates
import androidx.lifecycle.lifecycleScope
import com.base.locationsharewhite.BuildConfig
import com.base.locationsharewhite.R
import com.base.locationsharewhite.bean.ConstObject
import com.base.locationsharewhite.bean.ViewingBean
import com.base.locationsharewhite.databinding.ActivityLocationMapBinding
import com.base.locationsharewhite.helper.BaseActivity
import com.base.locationsharewhite.helper.MyApplication
import com.base.locationsharewhite.location.LocationPositionUtils
import com.base.locationsharewhite.location.LocationShareListUtils
import com.base.locationsharewhite.map.MapUtils.addLocationMarker
import com.base.locationsharewhite.map.MapUtils.getLatLngByLocationManager
import com.base.locationsharewhite.ui.views.DialogView.showMapTypeDialog
import com.base.locationsharewhite.ui.views.DialogView.showViewerMoreDialog
import com.base.locationsharewhite.utils.BarUtils
import com.base.locationsharewhite.utils.LogEx
import com.base.locationsharewhite.utils.PermissionUtils.checkLocationPermission
import com.base.locationsharewhite.utils.ToastUtils.toast
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch


class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapReadyCallback {

    private val TAG = "LocationMapActivity"
    private var map: GoogleMap? = null
    private lateinit var locationPresenter: LocationPresenter
    private lateinit var adapter: ViewingAdapter
    private var getLocationJob: Job? = null

    override val binding: ActivityLocationMapBinding by lazy {
        ActivityLocationMapBinding.inflate(layoutInflater)
    }

    private var myMarker: Marker? = null
    private var friendMarker: Marker? = null
    private var currentViewingBean: ViewingBean? = null

    override fun initView() {
        BarUtils.setStatusBarLightMode(this, true)
        BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
//        binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
        locationPresenter = LocationPresenter(this, lifecycleScope)

        if (isLanguageRecreate(MyApplication.locationMapLanguage)) {
            return
        }

        val mapFragment =
            supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
        mapFragment?.getMapAsync(this)

        showFriendGuideOrNoFriend()
        initAdapter()
        initViewingData()
    }

    private fun initAdapter() {

        adapter = ViewingAdapter(
            itemClick = { viewingBean ->

                if (currentViewingBean?.device != viewingBean.device) {
                    removeOldViewingMarker()
                    currentViewingBean = viewingBean
                    startGetLocationJob()
                }

                changeViewingBeanPosition(true, true, true)
            },
            moreClick = { anchorView, item ->
                showViewerMoreDialog(anchorView)
            }

        )
        binding.rvViewing.adapter = adapter
    }

    private fun cancelGetLocationJob() {
        currentViewingBean = null
        getLocationJob?.cancel()
        getLocationJob = null
        friendMarker?.remove()
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun startGetLocationJob() {
        getLocationJob?.cancel()
        getLocationJob = null
        getLocationJob = lifecycleScope.launch(Dispatchers.IO) {

            while (isActive) {
                currentViewingBean?.let { viewingBean ->
                    LocationPositionUtils.getLocation(viewingBean.device) { locatDate ->
                        currentViewingBean?.locatDate = locatDate
                        lifecycleScope.launch(Dispatchers.Main) {
                            if (BuildConfig.DEBUG) {
                                toast("getLocation ${locatDate?.latitude} ${locatDate?.longitude}")
                            }
                            val viewing = adapter.items.findLast { it.device == viewingBean.device }
                            viewing?.locatDate = locatDate
                            adapter.notifyDataSetChanged()

                            changeViewingBeanPosition(false, false, false)
                        }
                    }
                }
                if (currentViewingBean == null) {
                    friendMarker?.remove()
                    friendMarker = null
                }
                delay(10 * 1000L)
            }
        }
    }

    private fun showFriendGuideOrNoFriend() {
        if (ConstObject.noShowFriendsShareGuide) {
            binding.llFriendsGuide.visibility = View.GONE
            binding.llNoFriend.visibility = View.VISIBLE
        } else {
            binding.llFriendsGuide.visibility = View.VISIBLE
            binding.llNoFriend.visibility = View.GONE
        }
    }

    private fun initViewingData() {
        LocationShareListUtils.getShareList(
            viewingListCallBack = {
                runOnUiThread {
                    if (it.isEmpty()) {
                        showFriendGuideOrNoFriend()
                        adapter.submitList(listOf())
                        cancelGetLocationJob()
                    } else {
                        binding.llFriendsGuide.visibility = View.GONE
                        binding.llNoFriend.visibility = View.GONE
                        binding.rvViewing.visibility = View.VISIBLE
                        adapter.submitList(it)
                    }
                }
            }
        )
    }

    override fun initListener() {
        super.initListener()
        if (isLanguageRecreate(MyApplication.locationMapLanguage)) {
            return
        }
        onBackPressedDispatcher.addCallback {
            finishToMain()
        }
        binding.ivFanhui.setOnClickListener {
            onBackPressedDispatcher.onBackPressed()
        }

        binding.ivChangeMapType.setOnClickListener {
            map?.let { showMapTypeDialog(it) }
        }

        binding.tvGotIt.setOnClickListener {
            binding.llFriendsGuide.visibility = View.GONE
            if (adapter.items.isEmpty()) {
                binding.llNoFriend.visibility = View.VISIBLE
            }
        }
        binding.tvNoShowAgain.setOnClickListener {
            ConstObject.noShowFriendsShareGuide = true
            binding.llFriendsGuide.visibility = View.GONE
            if (adapter.items.isEmpty()) {
                binding.llNoFriend.visibility = View.VISIBLE
            }
        }
        binding.ivLocation.setOnClickListener {
            changeMyLocation(locationPresenter.getMyLocation(), true, true, true)
        }
        binding.ivRefresh.setOnClickListener {
            startRefreshAnimation()
            lifecycleScope.launch(Dispatchers.Main) {
                delay(2000)
                stopRefreshAnimation()
            }
            initViewingData()
        }
        binding.bottomSheet.setOnClickListener { }

    }

    private var valueAnimator: ValueAnimator? = null
    private fun startRefreshAnimation() {
        if (valueAnimator == null) {
            valueAnimator = ValueAnimator.ofFloat(0f, 360f)
            valueAnimator?.run {
                duration = 1000
                repeatMode = ValueAnimator.RESTART
                repeatCount = ValueAnimator.INFINITE
                interpolator = LinearInterpolator()
                addUpdateListener {
                    binding.ivRefresh.rotation = it.animatedValue as Float
                }
                start()
            }
        }
    }

    private fun stopRefreshAnimation() {
        valueAnimator?.cancel()
        valueAnimator = null
        binding.ivRefresh.rotation = 0f
    }

    override fun onMapReady(googleMap: GoogleMap) {
        LogEx.logDebug(TAG, "onMapReady")
        map = googleMap

        LogEx.logDebug(TAG, "onMapReady")
        val flag = changeMyLocation(locationPresenter.getMyLocation(), true, true, true)

        if (!flag) {
            locationPresenter.getGoogleServiceLocation()
            locationPresenter.oneShotLocationCallBack = {
                changeMyLocation(locationPresenter.getMyLocation(), true, true, true)
            }
        }
        locationPresenter.refreshLocationCallBack = {
            toast("updata ${it?.latitude} ${it?.longitude}")
            LogEx.logDebug(TAG, "myLocation ${it}")
            changeMyLocation(it, false, false, false)
        }
    }

    /**
     * 设置自己位置
     */
    private fun changeMyLocation(
        latLng: LatLng?,
        followCamera: Boolean,
        resetZoom: Boolean,
        changeZIndex: Boolean
    ): Boolean {
        initMyLocationMarker()

        if (changeZIndex) {
            changeMarkerZIndex(true)
        }

        latLng?.let {
            myMarker?.position = it

            if (followCamera) {
                if (resetZoom) {
                    map?.moveCamera(CameraUpdateFactory.newLatLngZoom(it, 15f))
                    myMarker?.showInfoWindow()
                } else {
                    map?.moveCamera(CameraUpdateFactory.newLatLng(it))
                }
            }
            return true
        }
        return false
    }

    /**
     * 初始化自己Marker
     */
    private fun initMyLocationMarker() {
        if (myMarker == null) {
            var myLatLng: LatLng? = getLatLngByLocationManager()
            if (myLatLng == null) {
                myLatLng = locationPresenter.googleLocation
            }
            myLatLng?.let {
                LogEx.logDebug(TAG, "getLastKnowLocation ${myLatLng.latitude} ${myLatLng.longitude}")
                val myAvatar = LayoutInflater.from(this).inflate(R.layout.avatar_me, null)
                myMarker = map?.addLocationMarker(myAvatar, myLatLng, getString(R.string.me))
            }
        }
    }

    /**
     * 改变他人位置
     */
    private fun changeViewingBeanPosition(changeCamera: Boolean, resetZoom: Boolean, changeZIndex: Boolean) {
        currentViewingBean?.let { viewingBean ->
            viewingBean.locatDate?.let { locatDate ->

                val latLng = LatLng(locatDate.latitude, locatDate.longitude)
                initViewingMarker(latLng, viewingBean.nickname)

                setViewingBeanMarker(latLng, changeCamera, resetZoom, changeZIndex)

            }
        }
    }

    /**
     * 初始化他人Marker
     */
    private fun initViewingMarker(latLng: LatLng, nickname: String) {
        if (friendMarker == null) {
            val friendAvatar = LayoutInflater.from(this).inflate(R.layout.avatar_friend, null)
            friendMarker = map?.addLocationMarker(friendAvatar, latLng, nickname)
        }

    }

    /**
     * 移除旧的他人Marker
     */
    private fun removeOldViewingMarker() {
        friendMarker?.remove()
        friendMarker = null
    }

    /**
     * 移动他人Marker
     */
    private fun setViewingBeanMarker(
        latLng: LatLng,
        changeCamera: Boolean,
        resetZoom: Boolean,
        changeZIndex: Boolean
    ) {
        if (changeCamera) {
            if (resetZoom) {
                map?.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
                friendMarker?.showInfoWindow()
            } else {
                map?.moveCamera(CameraUpdateFactory.newLatLng(latLng))
            }
        }
        friendMarker?.position = latLng
        LogEx.logDebug(TAG, "Viewing ${latLng}")
        if (changeZIndex) {
            changeMarkerZIndex(false)
        }
    }

    private fun changeMarkerZIndex(isShowMe: Boolean) {
        if (isShowMe) {
            myMarker?.zIndex = 2f
            friendMarker?.zIndex = 1f
        } else {
            myMarker?.zIndex = 1f
            friendMarker?.zIndex = 2f
        }
    }


    override fun onPause() {
        super.onPause()
        locationPresenter.cancelLocationUpdates()
        locationPresenter.cancelUploadJob()
    }

    override fun onResume() {
        super.onResume()

        val isRecreate = updateAppLanguage(MyApplication.locationMapLanguage) {
            MyApplication.locationMapLanguage = it
        }
        if (isRecreate) {
            return
        }

        if (checkLocationPermission()) {
            locationPresenter.requestLocationUpdates()
            locationPresenter.startUploadMyLocation()

        }
    }

}