package cz.muni.sutralog.ui.detail

import android.annotation.SuppressLint
import android.app.Activity.RESULT_OK
import android.app.DatePickerDialog
import android.content.DialogInterface
import android.content.Intent
import android.graphics.drawable.ColorDrawable
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 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.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
    }

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

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

        if(addRock){
            binding.toolbar.title = "New Rock"
        }

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

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

        binding.changeImageButton.setOnClickListener {
            imageChooser()
        }
    }

    val SELECT_PICTURE = 200

    fun imageChooser() {

        // create an instance of the
        // intent of the type image
        val i = Intent()
        i.type = "image/*"
        i.action = Intent.ACTION_GET_CONTENT

        // pass the constant to compare it
        // with the returned requestCode
        startActivityForResult(Intent.createChooser(i, "Select Picture"), SELECT_PICTURE)
    }

    // this function is triggered when user
    // selects the image from the imageChooser
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                val selectedImageUri = data?.data
                if (null != selectedImageUri) {
                    var fileName = selectedImageUri.path?.substringAfterLast("/")
                    var docFile = DocumentFile.fromSingleUri(requireContext(), selectedImageUri)
                    if (docFile != null) {
                        fileName = docFile.uri.toString()
                    }

                    val dstPath = RockEditFragmentArgs.fromBundle(requireArguments()).rock.folderPath
                    val dst = File(dstPath)
                    val source = File(fileName)
                 //   exportFile(source, dst)
                    binding.rockImage.setImageURI(selectedImageUri)
          /*          var fileName = selectedImageUri.path?.substringAfterLast("/")
                    var docFile = DocumentFile.fromSingleUri(requireContext(), selectedImageUri)
                    if (docFile != null) {
                        fileName = docFile.uri.toString()
                    }
                    var sourceFile = File(fileName)
                    val destFile = File(RockEditFragmentArgs.fromBundle(requireArguments()).rock.folderPath
                            + "/" + selectedImageUri.path?.substringAfterLast("/"))
                    sourceFile.copyTo(destFile, true, 16 * 1024);
                    binding.rockImage.setImageURI(Uri.fromFile(destFile)) */
                }
            }
        }
    }

    /*
    @Throws(IOException::class)
    private fun exportFile(src: File, dst: File): File? {

        //if folder does not exist
        if (!dst.exists()) {
            if (!dst.mkdir()) {
                return null
            }
        }
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val expFile = File(dst.path + File.separator + "IMG_" + timeStamp + ".jpg")
        var inChannel: FileChannel? = null
        var outChannel: FileChannel? = null
        try {
            inChannel = FileInputStream(src).channel
            outChannel = FileOutputStream(expFile).channel
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        }
        try {
            inChannel!!.transferTo(0, inChannel.size(), outChannel)
        } finally {
            inChannel?.close()
            outChannel?.close()
        }
        return expFile
    }

    @Throws(IOException::class)
    fun copyFile(sourceFile: File?, destFile: File) {
        if (!sourceFile?.exists()!!) {
            return;
        }

        val source = FileInputStream(sourceFile).getChannel();
        val destination = FileOutputStream(destFile).getChannel();
        if (destination != null && source != null) {
            destination.transferFrom(source, 0, source.size());
        }
        source?.close()
        destination?.close()
    }
*/

    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
        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)
    }
}