package kr.co.vividnext.sodalive.live.roulette.config

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Service
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.InputFilter
import android.view.LayoutInflater
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
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.Constants
import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.databinding.ActivityRouletteConfigBinding
import kr.co.vividnext.sodalive.live.roulette.RoulettePreviewDialog
import org.koin.android.ext.android.inject
import java.util.Locale
import java.util.concurrent.TimeUnit

class RouletteConfigActivity : BaseActivity<ActivityRouletteConfigBinding>(
    ActivityRouletteConfigBinding::inflate
) {
    private val viewModel: RouletteSettingsViewModel by inject()

    private lateinit var imm: InputMethodManager
    private lateinit var loadingDialog: LoadingDialog

    private val handler = Handler(Looper.getMainLooper())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val availableActive = intent.getBooleanExtra(
            Constants.EXTRA_ROULETTE_AVAILABLE_ACTIVE,
            true
        )

        binding.rlRouletteIsActive.visibility = if (availableActive) {
            View.VISIBLE
        } else {
            View.GONE
        }

        viewModel.availableActive = availableActive

        bindData()
        viewModel.getAllRoulette()
    }

    override fun setupView() {
        binding.tvBack.text = "룰렛 설정"
        binding.tvBack.setOnClickListener { finish() }

        loadingDialog = LoadingDialog(this, layoutInflater)
        imm = getSystemService(
            Service.INPUT_METHOD_SERVICE
        ) as InputMethodManager

        binding.etSetPrice.filters = arrayOf(InputFilter { source, start, end, _, _, _ ->
            // Only allow numeric input
            for (i in start until end) {
                if (!Character.isDigit(source[i])) {
                    return@InputFilter ""
                }
            }
            null
        })

        binding.ivRouletteIsActive.setOnClickListener { viewModel.toggleIsActive() }
        binding.ivAddOption.setOnClickListener { addOption() }

        binding.tvPreview.setOnClickListener {
            handler.postDelayed({
                imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0)
            }, 100)
            viewModel.onClickPreview()
        }

        binding.tvSave.setOnClickListener { _ ->
            handler.postDelayed({
                imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0)
            }, 100)

            viewModel.createOrUpdateRoulette {
                val resultIntent = Intent().apply { putExtra(Constants.EXTRA_RESULT_ROULETTE, it) }
                setResult(Activity.RESULT_OK, resultIntent)
                finish()
            }
        }

        binding.llSelectRoulette1.setOnClickListener {
            viewModel.selectRoulette(
                RouletteSettingsViewModel.SelectedRoulette.ROULETTE_1
            )
        }

        binding.llSelectRoulette2.setOnClickListener {
            viewModel.selectRoulette(
                RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2
            )
        }

        binding.llSelectRoulette3.setOnClickListener {
            viewModel.selectRoulette(
                RouletteSettingsViewModel.SelectedRoulette.ROULETTE_3
            )
        }
    }

    @SuppressLint("SetTextI18n")
    private fun bindData() {
        viewModel.selectedRouletteLiveData.observe(this) {
            deselectAllRoulette()
            when (it) {
                RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2 -> selectRouletteButton(
                    binding.ivSelectRoulette2,
                    binding.llSelectRoulette2,
                    binding.tvSelectRoulette2
                )

                RouletteSettingsViewModel.SelectedRoulette.ROULETTE_3 -> selectRouletteButton(
                    binding.ivSelectRoulette3,
                    binding.llSelectRoulette3,
                    binding.tvSelectRoulette3
                )

                else -> selectRouletteButton(
                    binding.ivSelectRoulette1,
                    binding.llSelectRoulette1,
                    binding.tvSelectRoulette1
                )
            }
        }

        viewModel.isActiveLiveData.observe(this) {
            binding.ivRouletteIsActive.setImageResource(
                if (it) R.drawable.btn_toggle_on_big else R.drawable.btn_toggle_off_big
            )
        }

        viewModel.optionsLiveData.observe(this) { updateOptionUi(it) }

        viewModel.toastLiveData.observe(this) { it?.let { showToast(it) } }

        viewModel.canLiveData.observe(this) {
            if (it > 0) {
                binding.etSetPrice.setText("$it")
            } else {
                binding.etSetPrice.setText("")
            }
        }

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

        viewModel.roulettePreviewLiveData.observe(this) {
            RoulettePreviewDialog(
                activity = this@RouletteConfigActivity,
                previewList = listOf(it),
                title = "룰렛 미리보기",
                layoutInflater = layoutInflater
            ).show()
        }

        viewModel.totalPercentageLiveData.observe(this) {
            binding.tvTotalPercentage.text = "( ${
                String.format(
                    Locale.KOREAN,
                    "%.2f%%",
                    it
                )
            } )"
        }

        compositeDisposable.add(
            binding.etSetPrice.textChanges().skip(1)
                .debounce(100, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe {
                    if (it.trim().isNotEmpty()) {
                        viewModel.can = it.toString().toInt()
                    }
                }
        )
    }

    private fun addOption() {
        val newOption = RouletteOption("", "")
        viewModel.addOption(newOption)
    }

    private fun updateOptionUi(options: List<RouletteOption>) {
        binding.llRouletteOptionContainer.removeAllViews()
        options.forEachIndexed { index, option ->
            binding.llRouletteOptionContainer.addView(createOptionView(index, option))
        }
    }

    @SuppressLint("SetTextI18n")
    private fun createOptionView(index: Int, option: RouletteOption): View {
        val optionView = LayoutInflater
            .from(applicationContext)
            .inflate(
                R.layout.layout_roulette_option,
                binding.llRouletteOptionContainer,
                false
            )

        val etOption = optionView.findViewById<EditText>(R.id.et_option)
        val tvOptionTitle = optionView.findViewById<TextView>(R.id.tv_option_title)
        val etPercentage = optionView.findViewById<EditText>(R.id.et_option_percentage)
        val tvDelete = optionView.findViewById<TextView>(R.id.tv_delete)

        etOption.setText(option.title)
        tvOptionTitle.text = "옵션 ${index + 1}"

        try {
            if (option.percentage.toFloat() > 0f) {
                etPercentage.setText(option.percentage)
            } else {
                etPercentage.setText("")
            }
        } catch (e: Exception) {
            etPercentage.setText("")
        }

        if (index == 0 || index == 1) {
            tvDelete.visibility = View.GONE
        } else {
            tvDelete.visibility = View.VISIBLE
            tvDelete.setOnClickListener { viewModel.deleteOption(index) }
        }

        compositeDisposable.add(
            etOption.textChanges().skip(1)
                .debounce(100, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe {
                    viewModel.inputOption(index, it.toString())
                }
        )

        compositeDisposable.add(
            etPercentage.textChanges().skip(1)
                .debounce(100, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe {
                    viewModel.inputOptionPercentage(index, it.toString())
                }
        )

        return optionView
    }

    private fun deselectAllRoulette() {
        binding.ivSelectRoulette1.visibility = View.GONE
        binding.ivSelectRoulette2.visibility = View.GONE
        binding.ivSelectRoulette3.visibility = View.GONE

        binding.llSelectRoulette1.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b)
        binding.tvSelectRoulette1.setTextColor(
            ContextCompat.getColor(
                applicationContext,
                R.color.color_3bb9f1
            )
        )

        if (viewModel.rouletteList.size > 0) {
            binding.llSelectRoulette2.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b)
            binding.tvSelectRoulette2.setTextColor(
                ContextCompat.getColor(
                    applicationContext,
                    R.color.color_ffcb14
                )
            )
        } else {
            binding.llSelectRoulette2.setBackgroundResource(R.drawable.bg_round_corner_6_7_777777)
            binding.tvSelectRoulette2.setTextColor(
                ContextCompat.getColor(
                    applicationContext,
                    R.color.color_ff14d9
                )
            )
        }

        if (viewModel.rouletteList.size > 1) {
            binding.llSelectRoulette3.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b)
            binding.tvSelectRoulette3.setTextColor(
                ContextCompat.getColor(
                    applicationContext,
                    R.color.color_3bb9f1
                )
            )
        } else {
            binding.llSelectRoulette3.setBackgroundResource(R.drawable.bg_round_corner_6_7_777777)
            binding.tvSelectRoulette3.setTextColor(
                ContextCompat.getColor(
                    applicationContext,
                    R.color.color_555555
                )
            )
        }
    }

    private fun selectRouletteButton(
        ivSelectRoulette: ImageView,
        llSelectRoulette: LinearLayout,
        tvSelectRoulette: TextView
    ) {
        ivSelectRoulette.visibility = View.VISIBLE
        llSelectRoulette.setBackgroundResource(
            when (viewModel.selectedRouletteLiveData.value) {
                RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2 -> R.drawable.bg_round_corner_6_7_ffcb14
                RouletteSettingsViewModel.SelectedRoulette.ROULETTE_3 -> R.drawable.bg_round_corner_6_7_ff14d9
                else -> R.drawable.bg_round_corner_6_7_3bb9f1
            }
        )
        tvSelectRoulette.setTextColor(
            ContextCompat.getColor(
                applicationContext,
                when (viewModel.selectedRouletteLiveData.value) {
                    RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2 -> R.color.black
                    else -> R.color.color_eeeeee
                }
            )
        )
    }
}
