package com.player.musicoo.activity

import android.annotation.SuppressLint
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar
import com.player.musicoo.R
import com.player.musicoo.adapter.DetailsListAdapter
import com.player.musicoo.adapter.SearchResultOtherAdapter
import com.player.musicoo.databinding.ActivityDetailsBinding
import com.player.musicoo.databinding.ActivitySearchMoreBinding
import com.player.musicoo.databinding.ActivitySingerDetailsBinding
import com.player.musicoo.fragment.MoHomeFragment
import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.bodies.ContinuationBody
import com.player.musicoo.innertube.models.bodies.SearchBody
import com.player.musicoo.innertube.requests.moPlaylistPage
import com.player.musicoo.innertube.requests.moSearchPage
import com.player.musicoo.innertube.requests.moSingerListPage
import com.player.musicoo.util.LogTag
import com.player.musicoo.util.LogTag.LogD
import com.player.musicoo.view.SearchResultOptimalView
import com.player.musicoo.view.SearchResultOtherView
import com.player.musicoo.view.SingerDetailsOtherView
import com.player.musicoo.view.SingerDetailsSongView
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select

class MoSearchMoreActivity : MoBaseActivity() {
    private val requests: Channel<Request> = Channel(Channel.UNLIMITED)

    enum class Request {
        TryAgain,
        MoreData,
    }

    companion object {
        const val SEARCH_MORE_QUERY = "search_more_query"
        const val SEARCH_MORE_PARAMS = "search_more_params"
    }

    private lateinit var binding: ActivitySearchMoreBinding
    private var query: String? = null
    private var params: String? = null
    private var list: MutableList<Innertube.SearchDataPage.SearchResult> = mutableListOf()
    private var currentContinuation: String? = null
    private var adapter: SearchResultOtherAdapter? = null

    override suspend fun main() {
        binding = ActivitySearchMoreBinding.inflate(layoutInflater)
        setContentView(binding.root)
        query = intent.getStringExtra(SEARCH_MORE_QUERY)
        params = intent.getStringExtra(SEARCH_MORE_PARAMS)
        if (query.isNullOrEmpty() || params.isNullOrEmpty()) {
            return
        }
        initImmersionBar()
        initView()
        initAdapter()
        initData(query!!, params!!)
        onReceive()
    }

    private fun initImmersionBar() {
        immersionBar {
            statusBarDarkFont(false)
            statusBarView(binding.view)
        }
    }

    private suspend fun onReceive() {
        while (isActive) {
            select<Unit> {
                requests.onReceive {
                    when (it) {
                        Request.TryAgain -> {
                            initData(query!!, params!!)
                        }

                        Request.MoreData -> {
                            if (!currentContinuation.isNullOrEmpty()) {
                                initDataMore(currentContinuation!!)
                            }else{
                                binding.refreshLayout.finishLoadMoreWithNoMoreData()
                            }
                        }
                    }
                }
            }
        }
    }

    private fun initView() {
        binding.backBtn.setOnClickListener {
            finish()
        }
        binding.tryAgainBtn.setOnClickListener {
            requests.trySend(Request.TryAgain)
        }
        binding.refreshLayout.setEnableRefresh(false)
        binding.refreshLayout.setEnableLoadMore(true)
        binding.refreshLayout.setOnLoadMoreListener {
            requests.trySend(Request.MoreData)
        }
    }

    private fun initAdapter() {
        adapter = SearchResultOtherAdapter(this, list)
        binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        binding.rv.adapter = adapter
    }

    private suspend fun initData(query: String, params: String) {
        showLoadingUi()
        Innertube.moSearchPage(SearchBody(query = query, params = params))?.onSuccess { result ->
            if (result.isNotEmpty()) {
                showDataUi()
                val title = result[0].title
                if (title.isNullOrEmpty()) {
                    binding.title.visibility = View.GONE
                } else {
                    binding.title.visibility = View.VISIBLE
                    binding.title.text = title
                }
                currentContinuation = result[0].continuation
                list.clear()
                list.addAll(result[0].searchResultList)
            } else {
                showNoContentUi()
            }
        }?.onFailure {
            showNoContentUi()
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private suspend fun initDataMore(continuation: String) {
        Innertube.moSearchPage(ContinuationBody(continuation = continuation))?.onSuccess { result ->
            currentContinuation = result.continuation
            if (currentContinuation.isNullOrEmpty()) {
                binding.refreshLayout.finishLoadMoreWithNoMoreData()
            }
            if (result.searchResultList.isNotEmpty()) {
                list.addAll(result.searchResultList)
                if (!isFinishing) {
                    adapter?.notifyDataSetChanged()
                }
                binding.refreshLayout.finishLoadMore(true)
            } else {
                binding.refreshLayout.finishLoadMoreWithNoMoreData()
            }
        }?.onFailure {
            binding.refreshLayout.finishLoadMoreWithNoMoreData()
        }
    }


    private fun showDataUi() {
        binding.loadingLayout.visibility = View.GONE
        binding.noContentLayout.visibility = View.GONE
    }

    private fun showLoadingUi() {
        binding.loadingLayout.visibility = View.VISIBLE
        binding.noContentLayout.visibility = View.GONE
    }

    private fun showNoContentUi() {
        binding.loadingLayout.visibility = View.GONE
        binding.noContentLayout.visibility = View.VISIBLE
    }
}