package com.base.locationsharewhite.ui.locationmap

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.animation.LinearInterpolator
import androidx.activity.addCallback
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.service.StayJobService
import com.base.locationsharewhite.service.StayJobService.Companion.requestServiceLocationUpdates
import com.base.locationsharewhite.ui.set.RenameActivity
import com.base.locationsharewhite.ui.set.RenameActivity.Companion.RENAME_VIEWING_NICK_NAME
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.checkBackgroundLocationPermission
import com.base.locationsharewhite.utils.PermissionUtils.checkLocationPermission
import com.base.locationsharewhite.utils.PermissionUtils.requestLocationAllowAllTime
import com.base.locationsharewhite.utils.SpStringUtils
import com.base.locationsharewhite.utils.SpStringUtils.VIEWING_NICKNAME_KEY
import com.base.locationsharewhite.utils.SpStringUtils._DEVICE_NICKNAME_
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, viewingBean: ViewingBean ->
                showViewerMoreDialog(anchorView,
                    renameAction = {
                        startActivity(Intent(this, RenameActivity::class.java).apply {
                            putExtra("doWhat", RENAME_VIEWING_NICK_NAME)
                            putExtra("device", viewingBean.device)
                            putExtra("nickName", viewingBean.localNickName ?: viewingBean.nickname)
                        })
                    },
                    deleteAction = {
                        LocationShareListUtils.deleteShare(viewingBean.device) { result ->
                            runOnUiThread {
                                if (result) {
                                    toast("delete success")
                                    binding.ivRefresh.callOnClick()
                                } else {
                                    toast("delete failed")
                                }
                            }
                        }
                    }
                )
            }
        )
        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 = { viewing ->
                val nickList = SpStringUtils.getSpStringList(VIEWING_NICKNAME_KEY)
                viewing.map { changeLocalNickName(it, nickList) }
                runOnUiThread {
                    if (viewing.isEmpty()) {
                        showFriendGuideOrNoFriend()
                        adapter.submitList(listOf())
                        cancelGetLocationJob()
                    } else {
                        binding.llFriendsGuide.visibility = View.GONE
                        binding.llNoFriend.visibility = View.GONE
                        binding.rvViewing.visibility = View.VISIBLE
                        adapter.submitList(viewing)
                    }
                }
            }
        )
    }

    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 { }
        binding.ivPermission.setOnClickListener {
            requestLocationAllowAllTime(launcher, jumpOutAction = {}, permissionAllowAction = {})
        }

    }

    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) {
            StayJobService.oneShotLocationCallBack = {
                changeMyLocation(locationPresenter.getMyLocation(), true, true, true)
            }
        }
        locationPresenter.refreshLocationCallBack = {
            if (BuildConfig.DEBUG) {
//                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 = StayJobService.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.cancelUploadJob()
        StayJobService.getGoogleServiceLocationDelay = 60
    }

    override fun onResume() {
        super.onResume()

//        val isRecreate = updateAppLanguage(MyApplication.locationMapLanguage) {
//            MyApplication.locationMapLanguage = it
//        }
//        if (isRecreate) {
//            return
//        }
        StayJobService.getGoogleServiceLocationDelay = 30

        if (!checkLocationPermission() || !checkBackgroundLocationPermission()) {
            binding.ivPermission.visibility = View.VISIBLE
        } else {
            binding.ivPermission.visibility = View.GONE
            locationPresenter.startUploadMyLocation()
            requestServiceLocationUpdates()
        }
        refreshNickName()
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun refreshNickName() = lifecycleScope.launch(Dispatchers.IO) {
        val nickList = SpStringUtils.getSpStringList(VIEWING_NICKNAME_KEY)

        adapter.items.map { viewing ->
            changeLocalNickName(viewing, nickList)
        }
        launch(Dispatchers.Main) {
            adapter.notifyDataSetChanged()
        }
    }

    private fun changeLocalNickName(viewingBean: ViewingBean, nickList: List<String>) {
        val deviceNicknameSp = nickList.find { it.contains(viewingBean.device) }
        deviceNicknameSp?.let { sp ->
            runCatching {
                val localNickName = sp.split(_DEVICE_NICKNAME_)[1]
                viewingBean.localNickName = localNickName
            }
        }
    }

}