package cz.muni.sutralog.ui.detail

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Activity.RESULT_OK
import android.app.DatePickerDialog
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.PermissionChecker.PERMISSION_DENIED
import androidx.core.content.PermissionChecker.checkSelfPermission
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.skydoves.colorpickerview.ColorEnvelope
import com.skydoves.colorpickerview.ColorPickerDialog
import com.skydoves.colorpickerview.flag.FlagMode
import com.skydoves.colorpickerview.listeners.ColorEnvelopeListener
import cz.muni.sutralog.MainActivity
import cz.muni.sutralog.R
import cz.muni.sutralog.data.CategoryPresentableListItem
import cz.muni.sutralog.data.RockPresentableListItem
import cz.muni.sutralog.databinding.RockEditBinding
import cz.muni.sutralog.lib.ColorPickerFlag
import cz.muni.sutralog.lib.SutralogStaticLib.Companion.dateToString
import cz.muni.sutralog.lib.SutralogStaticLib.Companion.stringToDate
import cz.muni.sutralog.repository.CategoryRepository
import cz.muni.sutralog.repository.RockRepository
import java.io.*
import java.nio.channels.FileChannel
import java.text.SimpleDateFormat
import java.util.*


class RockEditFragment  : Fragment() {

    private lateinit var binding: RockEditBinding

    private val rockRepository: RockRepository by lazy {
        RockRepository(requireContext())
    }
    private val categoryRepository: CategoryRepository by lazy {
        CategoryRepository(requireContext())
    }

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


    companion object {
        private val IMAGE_CHOOSE = 1000;
        private val PERMISSION_CODE = 1001;
    }

    private var imagePath: String = ""

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

        val rock = RockEditFragmentArgs.fromBundle(requireArguments()).rock
        val create = RockEditFragmentArgs.fromBundle(requireArguments()).add
        setCurrentRockValues(rock)
        initDatePicker(rock)
        initColorPicker(rock)

        val buttonText = requireActivity().findViewById<TextView>(R.id.change_image_text)
        if (create || rock.folderPath == null || rock.folderPath == "") {
            buttonText.text = "Přidat fotku"
        } else {
            buttonText.text = "Změnit fotku"
        }

        binding.toolbar.title = if (create) "Nový kámen" else "Upravit kámen"

        binding.toolbar.setNavigationOnClickListener{
            findNavController().navigateUp()
        }

        binding.toolbar.setOnMenuItemClickListener {
            when (it.itemId) {
                R.id.done -> {
                    saveValues(rock)
                    findNavController().navigateUp()
                }
            }
            true
        }

        binding.changeImageButton.setOnClickListener {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
                if (checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PERMISSION_DENIED ||
                    checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PERMISSION_DENIED){
                    val permissions = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    requestPermissions(permissions, RockEditFragment.PERMISSION_CODE)
                } else {
                    chooseImageGallery();
                }
            } else {
                chooseImageGallery();
            }
        }
    }

    private fun chooseImageGallery() {
        val intent = Intent(Intent.ACTION_PICK)
        intent.type = "image/*"
        resultLauncher.launch(intent)
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode){
            PERMISSION_CODE -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    chooseImageGallery()
                } else {
                    Toast.makeText(requireContext(),"Přístup nebyl povolen.", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

    var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val data: Intent? = result.data
            binding.rockImage.setImageURI(data?.data)

            imagePath = "content://media" + data?.data?.path
        }
    }

    private fun saveValues(oldRock: RockPresentableListItem) {
        oldRock.name = binding.rockName.text.toString()
        oldRock.categoryId = (binding.rockCategory.selectedItem as CategoryPresentableListItem).id
        binding.rockCount.text.toString().let {
            oldRock.count = if (it == "") null else it.toInt()
        }
        binding.rockDate.text.toString().let {
            oldRock.date = if (it == "") null else stringToDate(it)
        }
        oldRock.locality = binding.rockLocality.text.toString()
        binding.rockCoordinatesLatitude.text.toString().let {
            oldRock.latitude = if (it == "") null else it.toDouble()
        }
        binding.rockCoordinatesLongitude.text.toString().let {
            oldRock.longitude = if (it == "") null else it.toDouble()
        }
        oldRock.where = binding.rockWhere.text.toString()
        oldRock.from = binding.rockFrom.text.toString()
        oldRock.description = binding.rockDescription.text.toString()
        oldRock.comment = binding.rockComment.text.toString()
        oldRock.color = (binding.rockColorView.background as ColorDrawable).color

        if (imagePath != "") {
            oldRock.folderPath = imagePath
        }

        rockRepository.saveRock(oldRock)
    }

    private fun initColorPicker(rock: RockPresentableListItem) {
        binding.rockColorView.setOnClickListener {
            val builder = ColorPickerDialog.Builder(requireContext(), R.style.ColorPicker)
                .setTitle("Vyber si barvu")
                .setPositiveButton("Potvrdit",
                    ColorEnvelopeListener { colorEnvelope: ColorEnvelope, fromUser: Boolean ->
                        binding.rockColorView.setBackgroundColor(colorEnvelope.color)
                })
                .setNegativeButton("Zrušit") { dialogInterface: DialogInterface, i: Int ->
                    dialogInterface.dismiss()
                }
                .setNeutralButton("Zdědit barvu vybrané kategorie") { dialogInterface: DialogInterface, i: Int ->
                    binding.rockColorView.setBackgroundColor((binding.rockCategory.selectedItem as CategoryPresentableListItem).color)
                    dialogInterface.dismiss()
                }
                //.attachAlphaSlideBar(false)
            builder.colorPickerView.setInitialColor(rock.color)
            val bubbleFlag = ColorPickerFlag(requireContext(), R.layout.color_picker_flag)
            bubbleFlag.flagMode = FlagMode.ALWAYS
            builder.colorPickerView.flagView = bubbleFlag
            builder.show()
        }
    }

    @SuppressLint("SetTextI18n")
    private fun initDatePicker(rock: RockPresentableListItem) {
        binding.rockDate.setOnClickListener {
            val calendar = Calendar.getInstance()
            val year = calendar.get(Calendar.YEAR)
            val month = calendar.get(Calendar.MONTH)
            val day = calendar.get(Calendar.DAY_OF_MONTH)
            val datePickerDialog = DatePickerDialog(requireContext(), R.style.DatePicker,
                { _, selectedYear, selectedMonth, selectedDay ->
                    binding.rockDate.text = ("${selectedDay}.${(selectedMonth + 1)}.${selectedYear}")
                },
                if (rock.date != null) rock.date!!.year else year,
                if (rock.date != null) rock.date!!.monthValue else month,
                if (rock.date != null) rock.date!!.dayOfMonth else day
            )
            datePickerDialog.show()
        };
    }

    private fun setCurrentRockValues(rock: RockPresentableListItem) {
        val category = categoryRepository.getCategoryById(rock.categoryId)
        val categories = categoryRepository.getAllCategories()

        val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, categories)

        binding.rockName.setText(rock.name)
        binding.rockCategory.adapter = adapter
        binding.rockCategory.setSelection(categories.indexOf(category))
        rock.count?.let { binding.rockCount.setText(it.toString()) }
        rock.date?.let { binding.rockDate.text = dateToString(it) }
        binding.rockLocality.setText(rock.locality)
        rock.latitude?.let { binding.rockCoordinatesLatitude.setText(it.toString()) }
        rock.longitude?.let { binding.rockCoordinatesLongitude.setText(it.toString()) }
        binding.rockWhere.setText(rock.where)
        binding.rockFrom.setText(rock.from)
        binding.rockDescription.setText(rock.description)
        binding.rockComment.setText(rock.comment)
        binding.rockColorView.setBackgroundColor(rock.color)

        val path = rock.folderPath
        if (path != null && path != "") {
            binding.rockImage.setImageURI(Uri.parse(path))
        }
    }
}