package org.mosad.teapod.ui.activity.main.fragments

import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.launch
import org.mosad.teapod.databinding.FragmentLibraryBinding
import org.mosad.teapod.ui.activity.main.viewmodel.LibraryFragmentViewModel
import org.mosad.teapod.util.adapter.MediaItemListAdapter
import org.mosad.teapod.util.showFragment

class LibraryFragment : Fragment() {

    private lateinit var binding: FragmentLibraryBinding
    private lateinit var adapter: MediaItemListAdapter
    private val model: LibraryFragmentViewModel by viewModels()

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

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

        // TODO replace with pagination3
        // https://medium.com/swlh/paging3-recyclerview-pagination-made-easy-333c7dfa8797
        binding.recyclerMediaSearch.addOnScrollListener(PaginationScrollListener())

        adapter = MediaItemListAdapter(MediaItemListAdapter.OnClickListener {
            binding.searchText.clearFocus()
            activity?.showFragment(MediaFragment(it.id))
        })
        binding.recyclerMediaSearch.adapter = adapter

        binding.searchText.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String?): Boolean {
                query?.let { model.search(it) }
                return false // return false to dismiss the keyboard
            }

            override fun onQueryTextChange(newText: String?): Boolean {
                newText?.let { model.search(it) }
                return false // return false to dismiss the keyboard
            }
        })

        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                model.onUiState(viewLifecycleOwner.lifecycleScope) { uiState ->
                    when (uiState) {
                        is LibraryFragmentViewModel.UiState.Browse -> bindUiStateBrowse(uiState)
                        is LibraryFragmentViewModel.UiState.Search -> bindUiStateSearch(uiState)
                        is LibraryFragmentViewModel.UiState.Loading -> bindUiStateLoading()
                        is LibraryFragmentViewModel.UiState.Error -> bindUiStateError(uiState)
                    }
                }
            }
        }
    }

    private fun bindUiStateBrowse(uiState: LibraryFragmentViewModel.UiState.Browse) {
        adapter.submitList(uiState.itemList)
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun bindUiStateSearch(uiState: LibraryFragmentViewModel.UiState.Search) {
        adapter.submitList(uiState.itemList)
        adapter.notifyDataSetChanged() // this is needed, else the adapter will not update
    }

    private fun bindUiStateLoading() {
        // currently not used
    }

    private fun bindUiStateError(uiState: LibraryFragmentViewModel.UiState.Error) {
        // currently not used
        Log.e(javaClass.name, "A error occurred while loading a UiState: ${uiState.message}")
    }

    inner class PaginationScrollListener: RecyclerView.OnScrollListener() {

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)

            if (!model.isLazyLoading) {
                val layoutManager = recyclerView.layoutManager as? GridLayoutManager
                layoutManager?.let {
                    // adapter.itemCount - 10 to start loading a bit earlier than the actual end
                    if (layoutManager.findLastCompletelyVisibleItemPosition() >= (adapter.itemCount - 10)) {
                        model.onLazyLoad().invokeOnCompletion {
                            adapter.notifyItemRangeInserted(adapter.itemCount, model.PAGESIZE)
                        }
                    }
                }
            }
        }

    }

}
