package cz.muni.sutralog.ui.detail

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.app.DatePickerDialog
import android.content.ContentValues
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.view.LayoutInflater
import android.view.View
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.FileProvider
import androidx.core.content.FileProvider.getUriForFile
import androidx.core.content.PermissionChecker.PERMISSION_DENIED
import androidx.core.content.PermissionChecker.checkSelfPermission
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.BuildConfig
import cz.muni.sutralog.R
import cz.muni.sutralog.data.CategoryPresentableListItem
import cz.muni.sutralog.data.PhotoPresentableListItem
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.PhotoRepository
import cz.muni.sutralog.repository.RockRepository
import cz.muni.sutralog.ui.list.PhotoAdapter
import java.io.*
import java.text.SimpleDateFormat
import java.util.*


class RockEditFragment  : Fragment() {

    private lateinit var binding: RockEditBinding
    private lateinit var adapter: PhotoAdapter

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

    private var create: Boolean = false


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


    companion object {
        private val GALLERY_CODE = 1001;
        private val CAMERA_CODE = 1002;
    }

    private var imagePath: String = ""

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

        val rock = RockEditFragmentArgs.fromBundle(requireArguments()).rock
        create = RockEditFragmentArgs.fromBundle(requireArguments()).add

        adapter = PhotoAdapter(
            onItemClick = {

            },
            onItemLongClick = {true
            }
        )

        binding.rockImageRecyclerView.adapter = adapter

        setCurrentRockValues(rock)
        initDatePicker(rock)
        initColorPicker(rock)

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

        var photos = photoRepository.getPhotosByRockId(rock.id)
        if (create || photos == null || photos.isEmpty()) {
            binding.rockImageRecyclerView.visibility = GONE
        }

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

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

        binding.changeImageButton.setOnClickListener {
            val builder = AlertDialog.Builder(requireContext())
            builder.setMessage("Vyberte způsob přidání fotografie")
            builder.setPositiveButton("Galerie"){dialogInterface, which ->
                checkPermissionsAndOpenGallery()
            }
            builder.setNegativeButton("Fotoaparát"){dialogInterface, which ->
                checkPermissionsAndOpenCamera()
            }
            val alertDialog: AlertDialog = builder.create()
            alertDialog.show()
        }
    }

    private fun checkPermissionsAndOpenCamera() {
        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 ||
                checkSelfPermission(requireContext(), Manifest.permission.CAMERA) == PERMISSION_DENIED) {
                val permissions = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
                requestPermissions(permissions, CAMERA_CODE)
            } else {
                openCamera();
            }
        } else {
            openCamera();
        }
    }

    private var imageUri: Uri? = null
    private var images : List<String> = mutableListOf()

    private fun openCamera() {
        val values = ContentValues()
        values.put(MediaStore.Images.Media.TITLE, "Take a picture")
        imageUri = activity?.contentResolver?.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)

        // Create camera intent
        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)

        // Launch intent
        openCameraLauncher.launch(intent)
    }

    var openCameraLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            imagePath = "content://media" + imageUri!!.path
            images = images.plus(imagePath)

            val photo = PhotoPresentableListItem()
            photo.path = imagePath
            adapter.addItem(photo)
            binding.rockImageRecyclerView.visibility = VISIBLE
        }
    }

    private fun checkPermissionsAndOpenGallery() {
        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.GALLERY_CODE)
            } else {
                chooseImageGallery();
            }
        } else {
            chooseImageGallery();
        }
    }

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

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

    var openGalleryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val data: Intent? = result.data
            imagePath = "content://media" + data?.data?.path
            images = images.plus(imagePath)

            val photo = PhotoPresentableListItem()
            photo.path = imagePath
            adapter.addItem(photo)
            binding.rockImageRecyclerView.visibility = VISIBLE
        }
    }

    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

        var rockId = oldRock.id

        if(create){
            rockId = rockRepository.insertRock(oldRock)
        } else {
            rockRepository.updateRock(oldRock)
        }

        if (images.isNotEmpty()) {
            for(image in images){
                var photo: PhotoPresentableListItem = PhotoPresentableListItem()
                photo.rockId = rockId
                photo.path = image
                photoRepository.savePhoto(photo)
            }
            binding.rockImageRecyclerView.visibility = VISIBLE
        }
    }

    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 arrayAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, categories)

        binding.rockName.setText(rock.name)
        binding.rockCategory.adapter = arrayAdapter
        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)


        var photos = photoRepository.getPhotosByRockId(rock.id)
        if (photos.isNotEmpty()) {
            adapter.submitList(photos)
            binding.rockImageRecyclerView.visibility = VISIBLE
        }
    }
}