package com.github.libretube.fragments

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R
import com.github.libretube.adapters.ChannelAdapter
import com.github.libretube.databinding.FragmentChannelBinding
import com.github.libretube.util.ConnectionHelper
import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.SubscriptionHelper
import com.github.libretube.util.formatShort
import com.github.libretube.util.toID
import retrofit2.HttpException
import java.io.IOException

class ChannelFragment : Fragment() {
    private val TAG = "ChannelFragment"
    private lateinit var binding: FragmentChannelBinding

    private var channelId: String? = null
    private var channelName: String? = null

    var nextPage: String? = null
    private var channelAdapter: ChannelAdapter? = null
    private var isLoading = true
    private var isSubscribed: Boolean? = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            channelId = it.getString("channel_id").toID()
            channelName = it.getString("channel_name")
                ?.replace("/c/", "")
                ?.replace("/user/", "")
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentChannelBinding.inflate(layoutInflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.channelName.text = channelId
        binding.channelRecView.layoutManager = LinearLayoutManager(context)

        val refreshChannel = {
            binding.channelRefresh.isRefreshing = true
            fetchChannel()
            isSubscribed()
        }
        refreshChannel()
        binding.channelRefresh.setOnRefreshListener {
            refreshChannel()
        }

        binding.channelScrollView.viewTreeObserver
            .addOnScrollChangedListener {
                if (binding.channelScrollView.getChildAt(0).bottom
                    == (binding.channelScrollView.height + binding.channelScrollView.scrollY)
                ) {
                    // scroll view is at bottom
                    if (nextPage != null && !isLoading) {
                        isLoading = true
                        binding.channelRefresh.isRefreshing = true
                        fetchChannelNextPage()
                    }
                }
            }
    }

    private fun isSubscribed() {
        lifecycleScope.launchWhenCreated {
            isSubscribed = SubscriptionHelper.isSubscribed(channelId!!)
            if (isSubscribed == null) return@launchWhenCreated

            runOnUiThread {
                if (isSubscribed == true) {
                    binding.channelSubscribe.text = getString(R.string.unsubscribe)
                }

                binding.channelSubscribe.setOnClickListener {
                    binding.channelSubscribe.text = if (isSubscribed == true) {
                        SubscriptionHelper.unsubscribe(channelId!!)
                        isSubscribed = false
                        getString(R.string.subscribe)
                    } else {
                        SubscriptionHelper.subscribe(channelId!!)
                        isSubscribed = true
                        getString(R.string.unsubscribe)
                    }
                }
            }
        }
    }

    private fun fetchChannel() {
        fun run() {
            lifecycleScope.launchWhenCreated {
                val response = try {
                    if (channelId != null) RetrofitInstance.api.getChannel(channelId!!)
                    else RetrofitInstance.api.getChannelByName(channelName!!)
                } catch (e: IOException) {
                    binding.channelRefresh.isRefreshing = false
                    println(e)
                    Log.e(TAG, "IOException, you might not have internet connection")
                    return@launchWhenCreated
                } catch (e: HttpException) {
                    binding.channelRefresh.isRefreshing = false
                    Log.e(TAG, "HttpException, unexpected response")
                    return@launchWhenCreated
                }
                nextPage = response.nextpage
                isLoading = false
                binding.channelRefresh.isRefreshing = false
                runOnUiThread {
                    binding.channelScrollView.visibility = View.VISIBLE
                    binding.channelName.text = response.name
                    if (response.verified) {
                        binding.channelName.setCompoundDrawablesWithIntrinsicBounds(
                            0,
                            0,
                            R.drawable.ic_verified,
                            0
                        )
                    }
                    binding.channelSubs.text = resources.getString(
                        R.string.subscribers,
                        response.subscriberCount.formatShort()
                    )
                    if (response.description?.trim() == "") {
                        binding.channelDescription.visibility = View.GONE
                    } else {
                        binding.channelDescription.text = response.description?.trim()
                    }

                    ConnectionHelper.loadImage(response.bannerUrl, binding.channelBanner)
                    ConnectionHelper.loadImage(response.avatarUrl, binding.channelImage)

                    // recyclerview of the videos by the channel
                    channelAdapter = ChannelAdapter(
                        response.relatedStreams!!.toMutableList(),
                        childFragmentManager
                    )
                    binding.channelRecView.adapter = channelAdapter
                }
            }
        }
        run()
    }

    private fun fetchChannelNextPage() {
        fun run() {
            lifecycleScope.launchWhenCreated {
                val response = try {
                    RetrofitInstance.api.getChannelNextPage(channelId!!, nextPage!!)
                } catch (e: IOException) {
                    binding.channelRefresh.isRefreshing = false
                    println(e)
                    Log.e(TAG, "IOException, you might not have internet connection")
                    return@launchWhenCreated
                } catch (e: HttpException) {
                    binding.channelRefresh.isRefreshing = false
                    Log.e(TAG, "HttpException, unexpected response," + e.response())
                    return@launchWhenCreated
                }
                nextPage = response.nextpage
                channelAdapter?.updateItems(response.relatedStreams!!)
                isLoading = false
                binding.channelRefresh.isRefreshing = false
            }
        }
        run()
    }

    private fun Fragment?.runOnUiThread(action: () -> Unit) {
        this ?: return
        if (!isAdded) return // Fragment not attached to an Activity
        activity?.runOnUiThread(action)
    }
}
