package com.zxhy.simplefilesmanager.internalstorage

import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
import android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.PopupWindow
import androidx.activity.addCallback
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.zxhy.simplefilesmanager.R
import com.zxhy.simplefilesmanager.databinding.ActivityInternalStorageBinding
import com.zxhy.simplefilesmanager.databinding.PopupwindowMoreOpeartionBinding
import com.zxhy.simplefilesmanager.simpledata.JoListFileJo
import com.zxhy.simplefilesmanager.simpledata.JoListFileJo.Companion.joListFileJo
import com.zxhy.simplefilesmanager.simpledialog.SimpleFileDialog.showSimpleFileDialog
import com.zxhy.simplefilesmanager.simplejoke.JoActivityJoLauncher
import com.zxhy.simplefilesmanager.simplejoke.permission.JoPermissionJoCheckEx.jostorejoPermissionCheck
import com.zxhy.simplefilesmanager.simplejoke.permission.JoStoreJoPermissionEx.jorequestjoStoreFollow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File

class InternalStorageActivity : AppCompatActivity() {
    private lateinit var binding: ActivityInternalStorageBinding
    private val viewModel: InternalStorageViewModel by viewModels()
    private lateinit var launch: JoActivityJoLauncher
    private var currentMode: Int = BROWSER_MODE

    private val adapter by lazy {
        JoInternalJoStorageAdapter(
            allSelect = {
                binding.ivAll.isSelected = it
            },
            showEmpty = {
                showEmpty(isEmpty = it, showWrite = !it)
            }
        )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        launch = JoActivityJoLauncher(this)
        binding = ActivityInternalStorageBinding.inflate(layoutInflater)
        setContentView(binding.root)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        if (!jostorejoPermissionCheck()) {
            showPermissionSet()
        } else {
            initView()
            loadStorage()
        }
    }

    private fun showPermissionSet() {
        binding.flPermissionSet.visibility = View.VISIBLE

        binding.tvSet.setOnClickListener {
            jorequestjoStoreFollow(launch,
                agreeAction = {
                    initView()
                    loadStorage()
                },
                disAgreeAction = {

                }
            )
        }
    }

    private fun initView() {
        binding.flPermissionSet.visibility = View.GONE
        binding.llContent.visibility = View.VISIBLE

        binding.ivAll.setOnClickListener {
            it.isSelected = !it.isSelected
            adapter.toggleSelect(it.isSelected)
        }
        binding.ivWrite.setOnClickListener {
            operationMode()
        }
        binding.ivNewFile.setOnClickListener {
            showSimpleFileDialog { name ->
                val file = File(adapter.getCurrentDir(), name)
                if (file.isFile) return@showSimpleFileDialog
                if (!file.exists()) {
                    file.mkdirs()
                    adapter.notifyCurrentDir()
                }
            }
        }
        binding.rv.adapter = adapter

        onBackPressedDispatcher.addCallback {
            if (currentMode == BROWSER_MODE) {
                val isRoot = adapter.beforePage()
                if (isRoot)
                    finish()
            }
            if (currentMode == OPERATION_MODE) {
                browserMode()
            }

            if (currentMode == CONFIRM_MODE) {
                adapter.beforePage()
            }
        }
    }

    private fun browserMode() {
        currentMode = BROWSER_MODE
        binding.ivAll.visibility = View.GONE
        binding.ivWrite.visibility = View.VISIBLE
        adapter.changeSelect(false, isRemoveCannotNext = true)
        binding.llOperation.visibility = View.GONE
        binding.flConfirm.visibility = View.GONE
    }

    private fun operationMode() {
        currentMode = OPERATION_MODE
        binding.flConfirm.visibility = View.GONE
        binding.llOperation.visibility = View.VISIBLE
        adapter.changeSelect(true, canNext = false)
        binding.ivAll.isSelected = false
        showEmpty(showAll = true)
        binding.llMove.setOnClickListener {
            confirmMode("Move")
        }
        binding.llCopy.setOnClickListener {
            confirmMode("Copy")
        }
        binding.llShare.setOnClickListener {
            shareFiles()
        }
        binding.llMore.setOnClickListener {
            val files = adapter.getSelectData().map { it.toFile() }
            val size = files.size
            if (size == 0) return@setOnClickListener
            if (size == 1) {
                showMorePopupWindow(
                    2,
                    renameAction = { renameFile(files.first()) },
                    deleteAction = { deleteFiles(files) }
                )
            } else {
                showMorePopupWindow(1, deleteAction = { deleteFiles(files) })
            }
        }
    }

    private fun deleteFiles(files: List<File>) {
        viewModel.deleteFiles(files, ::operationFinish)
    }

    private fun renameFile(file: File) {
        val dir = file.parentFile
        showSimpleFileDialog(file.name, nameAction = {
            runCatching { file.renameTo(File(dir, it)) }
            operationFinish()
        })
    }

    @SuppressLint("SetTextI18n")
    private fun confirmMode(operation: String) {
        val selectFile = adapter.getSelectData()
        if (selectFile.isEmpty())
            return
        currentMode = CONFIRM_MODE
        binding.llOperation.visibility = View.GONE
        binding.ivAll.isSelected = false
        binding.ivAll.visibility = View.GONE
        binding.flConfirm.visibility = View.VISIBLE
        adapter.changeSelect(false, isAddCannotNext = true)
        binding.tvCancel.setOnClickListener {
            browserMode()
        }

        binding.tvConfirm.setOnClickListener {
            val files = adapter.getOperationList()
            val currentDir = adapter.getCurrentDir()
            when (operation) {
                "Move" -> {
                    binding.tvConfirm.text = "Motion"
                    viewModel.moveFiles(files, currentDir, ::operationFinish)
                }

                "Copy" -> {
                    binding.tvConfirm.text = "Paste"
                    viewModel.copyFiles(files, currentDir, ::operationFinish)
                }
            }
        }
    }

    private fun shareFiles() = runCatching {
        val list = adapter.getSelectData()
        val arrayList = ArrayList<Uri>()

        list.forEach {
            val uri = FileProvider.getUriForFile(this, "$packageName.provider", File(it.path))
            grantUriPermission(
                packageName, uri, FLAG_GRANT_READ_URI_PERMISSION
            )
            arrayList.add(uri)
        }
        val intent = Intent()
        intent.action = "android.intent.action.SEND_MULTIPLE"
        intent.type = "image/*"
        intent.putExtra("android.intent.extra.STREAM", arrayList)
        intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

        startActivity(intent)
        browserMode()
    }

    private fun operationFinish() = lifecycleScope.launch(Dispatchers.Main) {
        browserMode()
        adapter.notifyCurrentDir()
    }

    private fun loadStorage() {
        val root = Environment.getExternalStorageDirectory().listFiles()
        val datas = root?.map { joListFileJo(it) } ?: listOf()
        showEmpty(isEmpty = datas.isEmpty(), showWrite = true)
        adapter.setData(datas)
    }

    fun showEmpty(isEmpty: Boolean = false, showAll: Boolean = false, showWrite: Boolean = false) {

        binding.llEmpty.isVisible = isEmpty

        if (isEmpty) {
            binding.flAllWrite.visibility = View.GONE
        } else {
            binding.flAllWrite.visibility = View.VISIBLE
            binding.ivAll.isVisible = showAll
            binding.ivWrite.isVisible = showWrite
        }
    }

    companion object {
        const val BROWSER_MODE = 12
        const val OPERATION_MODE = 13
        const val CONFIRM_MODE = 18
    }


    @SuppressLint("ClickableViewAccessibility", "InflateParams")
    private fun showMorePopupWindow(
        count: Int = 2,
        renameAction: (() -> Unit)? = null,
        deleteAction: (() -> Unit)? = null
    ) {
        val popupWindowView = layoutInflater.inflate(R.layout.popupwindow_more_opeartion, null)
        val popupBinding = PopupwindowMoreOpeartionBinding.bind(popupWindowView)
        val itemHeight = resources.getDimensionPixelOffset(R.dimen.dp_40)
        if (count == 1) {
            popupBinding.llRename.visibility = View.GONE
        }
        val width =
            resources.getDimensionPixelSize(R.dimen.dp_108)
        val height = ViewGroup.LayoutParams.WRAP_CONTENT

        val popupWindow = PopupWindow(popupWindowView, width, height, true)
        popupWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        popupWindow.isOutsideTouchable = true
        popupWindow.isTouchable = true

        val intArr = intArrayOf(0, 0)
        binding.llMore.getLocationOnScreen(intArr)
        popupWindow.showAtLocation(
            binding.llOperation, Gravity.NO_GRAVITY,
            intArr[0], intArr[1] - itemHeight * count - 20,
        )
        popupBinding.llRename.setOnTouchListener { v, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    popupBinding.ivRename.isSelected = true
                    popupBinding.tvRename.isSelected = true
                }

                MotionEvent.ACTION_UP -> {
                    popupBinding.ivRename.isSelected = false
                    popupBinding.tvRename.isSelected = false
                }

                else -> {}
            }
            false
        }
        popupBinding.llDelete.setOnTouchListener { v, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    popupBinding.ivDelete.isSelected = true
                    popupBinding.tvDelete.isSelected = true
                }

                MotionEvent.ACTION_UP -> {
                    popupBinding.ivDelete.isSelected = false
                    popupBinding.tvDelete.isSelected = false
                }

                else -> {}
            }
            false
        }
        popupBinding.llRename.setOnClickListener {
            popupWindow.dismiss()
            renameAction?.invoke()
        }
        popupBinding.llDelete.setOnClickListener {
            popupWindow.dismiss()
            deleteAction?.invoke()
        }
    }
}