package kr.co.vividnext.sodalive.mypage.profile

import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import coil.load
import coil.transform.CircleCropTransformation
import com.github.dhaval2404.imagepicker.ImagePicker
import com.jakewharton.rxbinding4.widget.textChanges
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.RealPathUtil
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.ActivityProfileUpdateBinding
import kr.co.vividnext.sodalive.databinding.ItemLiveTagSelectedBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.mypage.profile.nickname.NicknameUpdateActivity
import kr.co.vividnext.sodalive.mypage.profile.password.ModifyPasswordActivity
import kr.co.vividnext.sodalive.mypage.profile.tag.MemberTagFragment
import kr.co.vividnext.sodalive.user.Gender
import org.koin.android.ext.android.inject
import java.util.concurrent.TimeUnit

class ProfileUpdateActivity : BaseActivity<ActivityProfileUpdateBinding>(
    ActivityProfileUpdateBinding::inflate
) {

    private val viewModel: ProfileUpdateViewModel by inject()

    private val imageResult =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            val resultCode = result.resultCode
            val data = result.data

            if (resultCode == RESULT_OK) {
                // Image Uri will not be null for RESULT_OK
                val fileUri = data?.data!!
                binding.ivProfile.background = null
                viewModel.updateProfileImage(fileUri) {
                    SharedPreferenceManager.profileImage = it
                    binding.ivProfile.load(it) {
                        crossfade(true)
                        transformations(CircleCropTransformation())
                    }
                }
            } else if (resultCode == ImagePicker.RESULT_ERROR) {
                Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
            }
        }

    private val tagFragment: MemberTagFragment by lazy {
        MemberTagFragment(viewModel.tags) { tag, isChecked ->
            when {
                isChecked -> {
                    viewModel.addTag(tag)
                    return@MemberTagFragment true
                }

                !isChecked -> {
                    viewModel.removeTag(tag)
                    return@MemberTagFragment true
                }

                else -> {
                    return@MemberTagFragment false
                }
            }
        }
    }

    private lateinit var loadingDialog: LoadingDialog

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel.getRealPathFromURI = {
            RealPathUtil.getRealPath(applicationContext, it)
        }

        bindData()
    }

    override fun onStart() {
        super.onStart()

        viewModel.getUserInfo()
    }

    private fun bindData() {
        compositeDisposable.add(
            binding.etBlog.textChanges().skip(1)
                .debounce(500, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe {
                    viewModel.blogUrl = it.toString()
                }
        )

        compositeDisposable.add(
            binding.etWebsite.textChanges().skip(1)
                .debounce(500, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe {
                    viewModel.websiteUrl = it.toString()
                }
        )

        compositeDisposable.add(
            binding.etYoutube.textChanges().skip(1)
                .debounce(500, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe {
                    viewModel.youtubeUrl = it.toString()
                }
        )

        compositeDisposable.add(
            binding.etInstagram.textChanges().skip(1)
                .debounce(500, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe {
                    viewModel.instagramUrl = it.toString()
                }
        )

        viewModel.genderLiveData.observe(this) {
            binding.tvMale.isSelected = false
            binding.tvFemale.isSelected = false
            binding.tvNone.isSelected = false

            when (it) {
                Gender.MALE -> binding.tvMale.isSelected = true
                Gender.FEMALE -> binding.tvFemale.isSelected = true
                Gender.NONE -> binding.tvNone.isSelected = true
                else -> {
                }
            }
        }

        viewModel.userInfoLiveData.observe(this) {
            binding.ivProfile.load(it.profileUrl) {
                crossfade(true)
                placeholder(R.drawable.bg_placeholder)
                transformations(CircleCropTransformation())
            }

            binding.tvEmail.text = it.email
            binding.tvNickname.text = it.nickname
            it.youtubeUrl?.let { url -> binding.etYoutube.setText(url) }
            it.instagramUrl?.let { url -> binding.etInstagram.setText(url) }
            it.websiteUrl?.let { url -> binding.etWebsite.setText(url) }
            it.blogUrl?.let { url -> binding.etBlog.setText(url) }
            binding.etIntroduce.setText(it.introduce)

            SharedPreferenceManager.nickname = it.nickname

            if (SharedPreferenceManager.role == "CREATOR") {
                binding.llSns.visibility = View.VISIBLE
                binding.llIntroduce.visibility = View.VISIBLE
                binding.llSelectTagWrapper.visibility = View.VISIBLE
            } else {
                binding.llSns.visibility = View.GONE
                binding.llIntroduce.visibility = View.GONE
                binding.llSelectTagWrapper.visibility = View.GONE
            }
        }

        viewModel.toastLiveData.observe(this) {
            it?.let {
                Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show()
            }
        }

        viewModel.isLoading.observe(this) {
            if (it) {
                loadingDialog.show(screenWidth)
            } else {
                loadingDialog.dismiss()
            }
        }

        viewModel.selectedTagLiveData.observe(this) {
            binding.llSelectTags.removeAllViews()
            binding.llSelectTags.visibility = if (it.isNotEmpty()) {
                View.VISIBLE
            } else {
                View.GONE
            }
            for (index in it.indices) {
                val tag = it[index]
                val itemView = ItemLiveTagSelectedBinding.inflate(layoutInflater)
                itemView.tvTag.text = tag
                itemView.ivRemove.setOnClickListener {
                    viewModel.removeTag(tag)
                }
                binding.llSelectTags.addView(itemView.root)

                if (index > 0) {
                    val layoutParams = itemView.root.layoutParams as LinearLayout.LayoutParams
                    layoutParams.marginStart = 10.dpToPx().toInt()
                    itemView.root.layoutParams = layoutParams
                }
            }
        }
    }

    override fun setupView() {
        binding.toolbar.tvBack.text = "프로필 수정"
        binding.toolbar.tvBack.setOnClickListener { finish() }

        loadingDialog = LoadingDialog(this, layoutInflater)

        compositeDisposable.add(
            binding.etIntroduce.textChanges()
                .debounce(500, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.io())
                .subscribe {
                    viewModel.introduce = it.toString()
                }
        )

        binding.tvMale.setOnClickListener {
            viewModel.changeGender(Gender.MALE)
        }

        binding.tvFemale.setOnClickListener {
            viewModel.changeGender(Gender.FEMALE)
        }

        binding.tvNone.setOnClickListener {
            viewModel.changeGender(Gender.NONE)
        }

        binding.ivPhotoPicker.setOnClickListener {
            ImagePicker.with(this)
                .crop()
                .galleryOnly()
                .galleryMimeTypes( // Exclude gif images
                    mimeTypes = arrayOf(
                        "image/png",
                        "image/jpg",
                        "image/jpeg"
                    )
                )
                .createIntent { imageResult.launch(it) }
        }

        binding.tvSelectTag.setOnClickListener {
            if (tagFragment.isAdded) return@setOnClickListener

            tagFragment.show(supportFragmentManager, tagFragment.tag)
        }

        binding.tvModifyPassword.setOnClickListener {
            startActivity(
                Intent(
                    applicationContext,
                    ModifyPasswordActivity::class.java
                )
            )
        }

        binding.tvSave.setOnClickListener {
            viewModel.updateProfile {
                finish()
            }
        }

        binding.tvChangeNickname.setOnClickListener {
            startActivity(
                Intent(
                    applicationContext,
                    NicknameUpdateActivity::class.java
                )
            )
        }
    }
}
