package com.gh.gamecenter.feature.selector

import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.AdapterView
import android.widget.PopupWindow
import androidx.recyclerview.widget.GridLayoutManager
import com.gh.gamecenter.common.base.fragment.BaseFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.LocalVideoEntity
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
import com.gh.gamecenter.core.utils.MD5Utils

import com.gh.gamecenter.common.utils.enlargeTouchArea
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
import com.gh.gamecenter.common.view.GridSpacingItemDecoration
import com.gh.gamecenter.core.provider.ICropImageProvider
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.MimeType

import com.gh.gamecenter.livedata.EventObserver
import com.gh.gamecenter.selector.databinding.FragmentLocalMediaBinding
import com.therouter.TheRouter

import com.zhihu.matisse.internal.entity.Album
import com.zhihu.matisse.internal.entity.Item
import com.zhihu.matisse.internal.entity.SelectionSpec
import com.zhihu.matisse.internal.model.AlbumCollection
import com.zhihu.matisse.internal.model.AlbumMediaCollection
import com.zhihu.matisse.internal.utils.PathUtils
import com.zhihu.matisse.ui.MatisseActivity
import java.util.ArrayList
import kotlin.collections.count
import kotlin.collections.forEach
import kotlin.collections.map
import kotlin.collections.toList
import kotlin.jvm.java
import kotlin.text.split

class LocalMediaFragment : BaseFragment<Any>(), AlbumMediaCollection.AlbumMediaCallbacks {

    private lateinit var binding: FragmentLocalMediaBinding
    private lateinit var adapter: LocalMediaAdapter
    private lateinit var viewModel: LocalMediaViewModel

    private lateinit var albumsSpanner: VideoAlbumsSpanner
    private lateinit var albumsAdapter: VideoAlbumsAdapter

    private var albumMediaCollection: AlbumMediaCollection? = null
    private var chooseType = ""
    private var maxChooseCount = 1
    private var isQuickChoose = false // 是否为快速选择模式 （选择图片后马上返回结果）

    private val albumCollection = AlbumCollection()
    private var isFirstAlbumLoad = true
    private var imageType = 0

    override fun getLayoutId(): Int = 0

    override fun getInflatedLayout(): View {
        binding = FragmentLocalMediaBinding.inflate(LayoutInflater.from(requireContext()), null, false)
        return binding.root
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        chooseType = arguments?.getString(EntranceConsts.KEY_TYPE) ?: ""
        maxChooseCount = savedInstanceState?.getInt(EntranceConsts.KEY_CHOOSE_MAX_COUNT, 1)
            ?: arguments?.getInt(EntranceConsts.KEY_CHOOSE_MAX_COUNT, 1)
                    ?: 1
        isQuickChoose = savedInstanceState?.getBoolean(EntranceConsts.KEY_QUICK_CHOOSE, false)
            ?: arguments?.getBoolean(EntranceConsts.KEY_QUICK_CHOOSE, false)
                    ?: false
        imageType = savedInstanceState?.getInt(EntranceConsts.KEY_IMAGE_TYPE, 0)
            ?: arguments?.getInt(EntranceConsts.KEY_IMAGE_TYPE, 0) ?: 0

        viewModel = viewModelProviderFromParent(LocalMediaViewModel.Factory(maxChooseCount))

        // 页面恢复时，恢复选中的数据
        if (savedInstanceState != null) {
            val savedSelectedItem: ArrayList<Item>? =
                savedInstanceState.getParcelableArrayList(EntranceConsts.KEY_VIDEO_LIST)
            if (savedSelectedItem != null) {
                for (selectedItem in savedSelectedItem) {
                    viewModel.addSelection(selectedItem)
                }
            }
        }
    }

    @SuppressLint("SetTextI18n")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        initAlbumsSpinner()

        if (chooseType == ChooseType.VIDEO.value) {
            binding.normalTitle.text = "本地视频"
        } else {
            binding.normalTitle.text = "本地图片"
        }

        binding.normalTitle.enlargeTouchArea(10F.dip2px())
        binding.arrowIv.setOnClickListener { binding.normalTitle.performClick() }
        binding.normalTitle.setOnClickListener {
            albumsSpanner.show(280F.dip2px())

            performArrowRotateAnimation(isClockWise = true)
        }

        binding.listRv.layoutManager = GridLayoutManager(requireContext(), 3)
        binding.listRv.addItemDecoration(GridSpacingItemDecoration(3, 4F.dip2px(), false))

        if (isQuickChoose) {
            binding.pieceMediaControl.root.visibility = View.GONE
        }

        adapter = LocalMediaAdapter(requireContext(), chooseType, isQuickChoose, viewModel)

        binding.listRv.adapter = adapter
        binding.listRefresh.isEnabled = false

        viewModel.selectedMediaListLiveData.observe(viewLifecycleOwner) {
            adapter.notifyDataSetChanged()
        }

        binding.pieceMediaControl.previewTv.setOnClickListener {
            viewModel.previewImage(onlySelected = true, 0, null, emptyMap())
        }

        binding.pieceMediaControl.confirmTv.setOnClickListener {
            viewModel.postSelectedResult()
        }

        viewModel.dataListLiveData.observe(viewLifecycleOwner) {
            adapter.submitList(it)
        }

        viewModel.resultLiveData.observe(viewLifecycleOwner) {
            if (it) {
                val intent = Intent()
                if (chooseType == ChooseType.VIDEO.value) {
                    val localVideoList = arrayListOf<LocalVideoEntity>()
                    viewModel.selectedItemList.forEach {
                        val path = PathUtils.getPath(requireContext(), it.contentUri)
                        if (path == null) {
                            toast("视频已不存在，请重新选择")
                            return@forEach
                        }
                        val id = MD5Utils.getUrlMD5(path) + System.currentTimeMillis()
                        val format = getFileFormat(it.mimeType)
                        localVideoList.add(
                            LocalVideoEntity(
                                id,
                                path,
                                contentUri = it.contentUri,
                                duration = it.duration,
                                format = format,
                                size = it.size
                            )
                        )
                    }
                    intent.putExtra(LocalVideoEntity::class.java.name, localVideoList)

                    requireActivity().setResult(Activity.RESULT_OK, intent)
                    requireActivity().finish()
                } else {
                    val data = viewModel.selectedItemList.map { it.contentUri }.toList()
                    val path = data.map { PathUtils.getPath(requireContext(), it) }.toList()

                    val imageProvider = TheRouter.get(ICropImageProvider::class.java)
                    val toIntent = imageProvider?.getCropImageIntent(data, imageType, mEntrance, requireContext())
                    if (toIntent != null) {
                        // 需要裁剪
                        startActivityForResult(toIntent, REQUEST_CROP_ICON)
                    } else {
                        intent.putParcelableArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION, ArrayList(data))
                        intent.putStringArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION_PATH, ArrayList(path))
                        requireActivity().setResult(Activity.RESULT_OK, intent)
                        requireActivity().finish()
                    }
                }


            }
        }

        viewModel.previewMediaLiveData.observe(viewLifecycleOwner, EventObserver {
            val previewFragment = LocalMediaPreviewFragment.getInstance(
                selectedItemList = it.previewList,
                album = it.album,
                positionInAlbum = it.positionInAlbum,
                originalUrlAndViewMap = it.urlAndViewMap,
                previewItem = it.previewItem
            )

            parentFragmentManager.beginTransaction()
                .replace(com.gh.gamecenter.selector.R.id.layout_activity_content, previewFragment)
                .addToBackStack(null)
                .commitAllowingStateLoss()
        })

        viewModel.selectedCountLiveData.observe(viewLifecycleOwner) {
            val isNotEmpty = it > 0

            binding.pieceMediaControl.previewTv.isEnabled = isNotEmpty
            binding.pieceMediaControl.confirmTv.isEnabled = isNotEmpty
            if (isNotEmpty) {
                binding.pieceMediaControl.previewTv.setTextColor(
                    com.gh.gamecenter.common.R.color.text_aw_primary.toColor(
                        requireContext()
                    )
                )
                binding.pieceMediaControl.previewTv.alpha = 1F
                binding.pieceMediaControl.confirmTv.alpha = 1F
                binding.pieceMediaControl.confirmTv.text =
                    "${getString(com.gh.gamecenter.common.R.string.confirm)}(${it})"
            } else {
                binding.pieceMediaControl.previewTv.setTextColor(
                    com.gh.gamecenter.common.R.color.text_aw_primary.toColor(
                        requireContext()
                    )
                )
                binding.pieceMediaControl.previewTv.alpha = 0.6F
                binding.pieceMediaControl.confirmTv.alpha = 0.6F
                binding.pieceMediaControl.confirmTv.text = getString(com.gh.gamecenter.common.R.string.confirm)
            }
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)

        outState.putInt(EntranceConsts.KEY_CHOOSE_MAX_COUNT, maxChooseCount)
        outState.putBoolean(EntranceConsts.KEY_QUICK_CHOOSE, isQuickChoose)
        outState.putParcelableArrayList(EntranceConsts.KEY_VIDEO_LIST, ArrayList(viewModel.selectedItemList))
    }

    private fun initAlbumsSpinner() {
        albumsSpanner = VideoAlbumsSpanner(requireContext())
        albumsAdapter = VideoAlbumsAdapter(requireContext())

        albumsSpanner.setPopupAnchorView(binding.normalToolbar)
        albumsSpanner.setAdapter(albumsAdapter)
        albumsSpanner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onNothingSelected(parent: AdapterView<*>?) {

            }

            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                albumCollection.setStateCurrentSelection(position)
                albumsAdapter.cursor.moveToPosition(position)
                albumsAdapter.updateSelectedPosition(position)
                val album = Album.valueOf(albumsAdapter.cursor)
                if (album.isAll && SelectionSpec.getInstance().capture) {
                    album.addCaptureCount()
                }

                binding.normalTitle.text = album.getDisplayName(requireContext())

                loadMedia(album)
            }
        }

        albumsSpanner.setDismissListener(PopupWindow.OnDismissListener {
            performArrowRotateAnimation(isClockWise = false)
        })

        // 必须加这行代码，[SelectionSpec]是单例模式，下次使用必须先更新MimeType
        val mimeType = if (chooseType == ChooseType.VIDEO.value) {
            MimeType.ofVideo()
        } else {
            MimeType.ofImage()
        }
        Matisse.from(this).choose(mimeType).showSingleMediaType(true).maxSelectable(maxChooseCount)

        albumCollection.onCreate(requireActivity(), object : AlbumCollection.AlbumCallbacks {
            override fun onAlbumLoad(cursor: Cursor?) {
                if (isFirstAlbumLoad) {
                    isFirstAlbumLoad = false
                    albumsAdapter.swapCursor(cursor)
                    mBaseHandler.post {
                        cursor?.moveToPosition(albumCollection.currentSelection)
                        val album = Album.valueOf(cursor)
                        if (album.isAll && SelectionSpec.getInstance().capture) {
                            album.addCaptureCount()
                        }
                        loadMedia(album)
                    }
                }
            }

            override fun onAlbumReset() {
                // do nothing
            }
        })
        albumCollection.loadAlbums()
    }

    private fun performArrowRotateAnimation(isClockWise: Boolean) {
        val arrowIv: View = binding.arrowIv

        val startAngle = if (isClockWise) 0F else 180F
        val endAngle = if (isClockWise) 180F else 360F

        val clockwiseAnimator = ObjectAnimator.ofFloat(arrowIv, "rotation", startAngle, endAngle)
        clockwiseAnimator.duration = 200
        clockwiseAnimator.start()
    }

    private fun getFileFormat(mimeType: String?): String {
        var format = ""
        tryWithDefaultCatch {
            if (mimeType != null) {
                val split = mimeType.split("/")
                format = if (split.count() >= 2) {
                    split[1]
                } else {
                    mimeType
                }
            }
        }
        return format
    }

    override fun onAlbumMediaReset() {
        viewModel.updateAlbumCursor(null)
    }

    override fun onAlbumMediaLoad(cursor: Cursor?) {
        viewModel.updateAlbumCursor(cursor = cursor)
        viewModel.refreshAlbumMediaData()
        binding.reuseNoneData.reuseNoneData.visibility = View.GONE
        binding.reuseLlLoading.root.visibility = View.GONE
        binding.reuseNoConnection.root.visibility = View.GONE
        binding.listRefresh.isRefreshing = false
    }

    fun loadMedia(album: Album) {
        albumMediaCollection?.onDestroy()

        albumMediaCollection = AlbumMediaCollection()
        albumMediaCollection?.onCreate(requireActivity(), this@LocalMediaFragment)

        viewModel.updateAlbum(album)

        albumMediaCollection?.load(album)
    }

    override fun onDestroy() {
        super.onDestroy()
        albumMediaCollection?.onDestroy()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == Activity.RESULT_OK && data != null) {
            when (requestCode) {
                REQUEST_CROP_ICON -> {
                    // 裁剪成功
                    if (data != null) {
                        val intent = Intent()
                        intent.putExtras(data)
                        requireActivity().setResult(Activity.RESULT_OK, intent)
                        requireActivity().finish()
                    }
                }
            }
        }
    }

    companion object {
        private const val REQUEST_CROP_ICON = 13
    }

}