package com.gh.gamecenter.video.poster.video

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.GridLayoutManager
import com.gh.gamecenter.CropImageActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.PermissionHelper.checkStoragePermissionBeforeAction
import com.gh.gamecenter.common.view.cropbox.CropBoxStyle
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.FragmentVideoCoverEditBinding
import com.gh.gamecenter.entity.VideoEntity
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.video.poster.video.VideoPosterViewModel.Companion.SELECTED_IMAGE_POSITION
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.ShapeAppearanceModel
import com.halo.assistant.HaloApp
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.internal.utils.PathUtils
import java.io.File
import java.io.FileOutputStream

class VideoPosterFragment : BaseFragment<Any>() {

    private lateinit var binding: FragmentVideoCoverEditBinding
    private lateinit var viewModel: VideoPosterViewModel

    var videoPath: String? = null

    var videoEntity: VideoEntity? = null

    private lateinit var adapter: VideoPosterReviewAdapter

    private lateinit var takePhotoLauncher: ActivityResultLauncher<Unit>

    override fun getInflatedLayout(): View {
        return View(requireContext())
    }

    override fun getLayoutId(): Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        videoPath = arguments?.getString(EntranceConsts.KEY_PATH_VIDEO)
        videoEntity = arguments?.getParcelable<VideoEntity>(EntranceConsts.KEY_VIDEO_ENTITY)
        super.onCreate(savedInstanceState)

        val videoCoverCache =
            SPUtils.getString(Constants.SP_VIDEO_COVER_CACHE).toObject<VideoPosterViewModel.VideoCoverCache>()
        val factory =
            VideoPosterViewModel.Factory(HaloApp.getInstance().application, videoPath, videoEntity, videoCoverCache)
        viewModel = ViewModelProviders.of(this, factory).get(VideoPosterViewModel::class.java)

        takePhotoLauncher = registerForActivityResult(object : ActivityResultContract<Unit, Intent?>() {
            override fun createIntent(context: Context, input: Unit): Intent {
                return LocalMediaActivity.getIntent(
                    context,
                    ChooseType.IMAGE,
                    1,
                    "视频封面编辑"
                )
            }

            override fun parseResult(resultCode: Int, intent: Intent?): Intent? {
                return intent
            }
        }) {
            if (it != null) {
                val uris = Matisse.obtainResult(it)
                if (uris.isNotEmpty()) {
                    val path = PathUtils.getPath(requireContext(), uris.first())
                    if (path != null) {
                        val ivZoom = binding.cropImageCustom.cropImageZoomView
                        val bitmap = BitmapUtils.getBitmapByFile(path, ivZoom.width, ivZoom.height)
                        if (bitmap != null) {
                            val videoPreview = VideoPosterViewModel.VideoPreview(0, bitmap, null)
                            viewModel.setSelectedImage(videoPreview)
                        }
                    }
                }
            }
        }
    }

    override fun initView(view: View?) = Unit

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

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

        adapter = VideoPosterReviewAdapter(requireContext(), viewModel)
        binding.rvImages.layoutManager = GridLayoutManager(requireContext(), 10)
        binding.rvImages.adapter = adapter

        binding.ivTakePhoto.shapeAppearanceModel = ShapeAppearanceModel()
            .toBuilder()
            .setAllCorners(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
            .build()
        binding.ivTakePhoto.clipToOutline = true

        binding.ivPreviewBorder.shapeAppearanceModel = ShapeAppearanceModel()
            .toBuilder()
            .setAllCorners(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
            .build()
        binding.ivPreviewBorder.strokeWidth = 4F.dip2px().toFloat()
        binding.ivPreviewBorder.strokeColor = ColorStateList.valueOf(Color.parseColor("#2496FF"))
        binding.ivPreviewBorder.clipToOutline = true

        binding.cropImageCustom.setCropBoxStyle(CropBoxStyle.Rectangle(23F / 41))

        binding.ivTakePhoto.setOnClickListener {
            val videoPreview = viewModel.selectedImage.value
            if (videoPreview == null) {
                checkStoragePermissionBeforeAction(requireContext()) { takePhotoLauncher.launch(Unit) }
            } else {
                viewModel.setPreviewImage(SELECTED_IMAGE_POSITION, videoPreview)
            }
        }

        binding.ivRemove.setOnClickListener {
            viewModel.setSelectedImage(null)
            if (viewModel.previewPosition.value == SELECTED_IMAGE_POSITION) {
                adapter.getItem(0)?.let {
                    viewModel.setPreviewImage(0, it)
                }
            }
        }

        binding.tvCancel.setOnClickListener {
            activity?.finish()
        }

        binding.tvSubmit.setOnClickListener {
            activity?.let {
                val clipPath = it.cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".jpg"
                binding.cropImageCustom.savePicture(clipPath)

                saveVideoOriginalCoverToLocal(it)

                val data = Intent()
                data.putExtra(CropImageActivity.RESULT_CLIP_PATH, clipPath)
                it.setResult(Activity.RESULT_OK, data)
                it.finish()
            }
        }

        with(viewModel) {
            videoPreviewsLiveData.observeNonNull(viewLifecycleOwner, callback = {
                adapter.submitList(it)
            })

            previewLiveData.observeNonNull(viewLifecycleOwner, callback = {
                binding.cropImageCustom.reset()
                it.values?.let(binding.cropImageCustom::setTransformationValues)
                if (it.thumbs != null) {
                    binding.cropImageCustom.setBitmap(it.thumbs)
                } else if (it.thumbsUrl != null) {
                    ImageUtils.picasso
                        .load(Uri.parse(it.thumbsUrl))
                        .into(binding.cropImageCustom.cropImageZoomView)
                }
            })

            selectedImage.observe(viewLifecycleOwner) {
                if (it == null) {
                    binding.ivTakePhoto.setImageResource(R.drawable.ic_video_cover_edit_take_photo)
                } else {
                    binding.ivTakePhoto.setImageBitmap(it.thumbs)
                }
                binding.ivRemove.goneIf(it == null)
            }

            previewPosition.observe(viewLifecycleOwner) {
                setSelectedImageSelected(it == SELECTED_IMAGE_POSITION)
                adapter.setPreviewPosition(it)
            }
        }
    }

    /**
     * 将封面原图保存在本地，以便下次编辑时显示
     */
    private fun saveVideoOriginalCoverToLocal(context: Context) {
        val preview = viewModel.previewLiveData.value
        if (preview != null) {
            val position = viewModel.previewPosition.value ?: -2
            var cache: VideoPosterViewModel.VideoCoverCache? = null
            val values = binding.cropImageCustom.transformationValues
            if (preview.thumbs != null) {
                val path = saveToInternalStorage(context, preview.thumbs)
                if (path != null) {
                    cache = VideoPosterViewModel.VideoCoverCache(position, localPath = path, values = values)
                }
            } else if (preview.thumbsUrl != null) {
                cache = VideoPosterViewModel.VideoCoverCache(position, url = preview.thumbsUrl, values = values)
            }
            val json = cache?.toJson()
            if (json != null) {
                SPUtils.setString(Constants.SP_VIDEO_COVER_CACHE, json)
            }
        }
    }

    private fun setSelectedImageSelected(isSelected: Boolean) {
        if (isSelected) {
            binding.ivTakePhoto.strokeWidth = 6F.dip2px().toFloat()
            binding.ivTakePhoto.strokeColor = ColorStateList.valueOf(Color.parseColor("#232323"))
        } else {
            binding.ivTakePhoto.strokeWidth = 0F
        }
        binding.ivPreviewBorder.goneIf(!isSelected)
    }

    // 保存到内部存储
    private fun saveToInternalStorage(
        context: Context,
        bitmap: Bitmap
    ): String? {
        try {
            val file = createVideoCoverFile(context)
            // 将图片保存到文件
            FileOutputStream(file).use { fos ->
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
                fos.flush()
            }

            return file.absolutePath
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
    }

    companion object {

        private const val VIDEO_COVER_DIRECTORY_NAME = "videoCover"

        fun createVideoCoverFile(context: Context): File {
            // 获取应用私有目录
            val directory = context.getDir(VIDEO_COVER_DIRECTORY_NAME, Context.MODE_PRIVATE)

            // 创建文件
            return File(directory, "cover_image.jpg")
        }

        /**
         * 清理上次裁剪图片留下的缓存文件
         */
        fun clearVideoCoverCache(context: Context) {
            SPUtils.setString(Constants.SP_VIDEO_COVER_CACHE, "")
            context.getDir(VIDEO_COVER_DIRECTORY_NAME, Context.MODE_PRIVATE).let { directory ->
                directory.listFiles()?.forEach { it.delete() }
            }
        }

        fun newInstance() = VideoPosterFragment()
    }


}