package com.develop.step.details

import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.activity.viewModels
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.blankj.utilcode.util.ToastUtils
import com.develop.food.base.http.Resource
import com.develop.food.base.repo.CURRENT_USER_ID
import com.develop.food.base.repo.FoodDataProvider
import com.develop.food.base.repo.entity.UserFavoriteRecipes
import com.develop.food.base.router.Screens
import com.develop.food.base.router.navigateTo
import com.develop.food.base.ui.BaseActivity
import com.develop.food.base.utils.*
import com.develop.step.DownloadFailedDialog
import com.develop.step.R
import com.develop.step.RecipeDeleteConfirmDialog
import com.develop.step.ShareQRCodeDialog
import com.develop.step.databinding.ActivityCookDetailBinding
import com.develop.step.model.CookDetailInfo
import com.develop.step.widgets.AmountSelectDialog
import java.util.*

@Route(path = Screens.Cook.COOK_DETAIL)
class CookDetailActivity : BaseActivity<ActivityCookDetailBinding>() {

    /**
     * source=local为本地菜谱
     * source=remote为网络菜谱
     */
    @JvmField
    @Autowired(name = "source")
    var cookSource: String? = "remote"

    @JvmField
    @Autowired(name = "number")
    var recipeNumber: String? = null

    @JvmField
    @Autowired(name = "isLike")
    var isLike: Boolean = false

    @JvmField
    @Autowired(name = "recipesEdition")
    var recipesEdition: String? = "1.0"

    private var hideDetail = false
    private val hideViews = mutableListOf<View>()
    private val allTabViews = mutableListOf<View>()
    private val viewModel by viewModels<CookDetailViewModel>()
    private val starViews = mutableListOf<View>()
    private val shareQRCodeDialog by lazy {
        ShareQRCodeDialog()
    }
    private val dowloadFialDialog by lazy {
        DownloadFailedDialog()
    }

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

        ARouter.getInstance().inject(this)
        binding.startLayout.let {
            starViews.add(it.ivStar1)
            starViews.add(it.ivStar2)
            starViews.add(it.ivStar3)
            starViews.add(it.ivStar4)
            starViews.add(it.ivStar5)
        }

        binding.ivTab1.setOnClickListener {
            selectTab(TAB_SOURCE)
        }
        binding.ivTab2.setOnClickListener {
            selectTab(TAB_DESC)
        }
        binding.ivTab3.setOnClickListener {
            selectTab(TAB_TOOLS)
        }
        binding.ivTab4.setOnClickListener {
            selectTab(TAB_SERVE)
        }
        binding.clStartCooking.setOnClickListener {
            if (cookSource == "remote") {
                if (viewModel.isDownloadSuccess()) {
                    navigateTo(Screens.Cook.COOK_STEP2) {
                        withString("number", recipeNumber)
                    }
                } else if (!viewModel.isDownloading()) {
                    binding.tvDownload.setText(R.string.downloading)
                    viewModel.downloadRecipe()
                }
            } else {
                navigateTo(Screens.Cook.COOK_STEP2) {
                    withString("number", recipeNumber)
                }
            }
        }
        if (isLike) {
            binding.ivLike.setBackgroundResource(R.drawable.ic_like)
        } else {
            binding.ivLike.setBackgroundResource(R.drawable.ic_unlike)
        }
        binding.likeLayout.setOnClickListener {
            //收藏/取消收藏
            if (isLike) {
                isLike = false
                FoodDataProvider.getUserDatabase().runInTransaction {
                    FoodDataProvider.getUserDatabase().userInfoDao().removeFavoriteRecipe(
                        CURRENT_USER_ID, recipeNumber ?: ""
                    )
                }
                binding.ivLike.setBackgroundResource(R.drawable.ic_unlike)
            } else {
                isLike = true
                binding.ivLike.setBackgroundResource(R.drawable.ic_like)
                FoodDataProvider.getUserDatabase().runInTransaction {
                    FoodDataProvider.getUserDatabase().userInfoDao().insertFavoriteRecipe(
                        UserFavoriteRecipes(CURRENT_USER_ID, recipeNumber ?: "")
                    )
                }
            }
        }
        binding.tvMoreScore.setOnClickListener {
            navigateTo(Screens.Cook.COOK_EVALUATE) {
                withString("recipeId", recipeNumber)
            }
        }
        binding.tvMoreDelete.setOnClickListener {
            binding.clFuncMore.setGone()
            showDeleteRecipeDialog()
        }
        binding.tvMoreShare.setOnClickListener {
            val number = viewModel.getRecipeLiveData().value?.recipe?.number
            if (number.isNullOrEmpty()) {
                return@setOnClickListener
            }
            binding.clFuncMore.setGone()
            shareQRCodeDialog.apply {
                recipeNum = number
                showDialog(supportFragmentManager,"ShareQRCodeDialog")
            }
        }
        binding.viewServing.setOnClickListener {
            showAmountSelectDialog()
        }
        binding.tvServingSize.setOnClickListener {
            showAmountSelectDialog()
        }
        binding.viewBack.setOnClickListener {
            finish()
        }
        initViews()
        initData()
    }

    private fun initViews() {
        if (cookSource == "local") {
            binding.tvDownload.setText(R.string.start_cooking)
            binding.viewProgress.setButtonColor(Color.RED)
            binding.viewIcon.setImageResource(R.drawable.ic_detail_cook_start)
        } else {
            binding.tvDownload.text = getString(R.string.download).uppercase(Locale.ROOT)
            binding.viewProgress.setButtonColor(Color.parseColor("#1296db"))
            binding.viewIcon.setImageResource(R.drawable.ic_detail_cook_download)
        }
        binding.viewHide.setOnClickListener {
            hideDetail = !hideDetail
            if (hideDetail) {
                binding.viewHide.setBackgroundResource(R.drawable.ic_detail_hide)
            } else {
                binding.viewHide.setBackgroundResource(R.drawable.ic_detail_show)
            }
            for (view in hideViews) {
                if (hideDetail) {
                    view.visibility = View.INVISIBLE
                } else {
                    view.visibility = View.VISIBLE
                }
            }
        }
        binding.viewMore.setOnClickListener {
            binding.clFuncMore.setVisible()
        }
        binding.viewMoreClose.setOnClickListener {
            binding.clFuncMore.setGone()
        }
        binding.clFuncMore.setOnClickListener {
            binding.clFuncMore.setGone()
        }
        hideViews.let {
            it.add(binding.viewIcon1)
            it.add(binding.viewIcon2)
            it.add(binding.tvFoodTime)
            it.add(binding.tvEasy)
            it.add(binding.startLayout.root)
        }
        allTabViews.add(binding.ivTab1)
        allTabViews.add(binding.ivTab2)
        allTabViews.add(binding.ivTab3)
        allTabViews.add(binding.ivTab4)
        selectTab(TAB_SOURCE)
    }

    private fun initData() {
        viewModel.queryRecipe(
            recipeNumber ?: "",
            cookSource == "remote",
            recipesEdition ?: "1.0"
        )
        viewModel.getRecipeLiveData().observe(this) {
            updateCookDetail(it)
        }
        viewModel.getErrorCodeLiveData().observe(this) {
            if (it == CookDetailViewModel.ERR_NO_RECIPE_MATCH) {
                ToastUtils.showShort("No match recipe found!")
                finish()
            }
        }
        viewModel.starCountLiveData.observe(this) {
            selectStar(it)
            binding.startLayout.tvStarNum.text = "(${it})"
        }
        viewModel.getDownloadState().observe(this) {
            updateDownloadButton(it)
        }
        viewModel.portionSizeLiveData.observe(this) {
            val jarsCount = (it.portionSize ?: 1).toString() + " " + getString(R.string.jar)
            binding.tvJarCount.text = jarsCount
        }
    }

    @SuppressLint("SetTextI18n")
    private fun updateCookDetail(detail: CookDetailInfo) {
        val bannerImg = FoodDataProvider.getResourcePath(detail.recipe.photoPath)
        binding.ivTopBanner.loadCrossFade(bannerImg)
        binding.tvFoodName.text = detail.recipe.name
        val timeDescBuilder = StringBuilder()
        timeDescBuilder.append(getString(R.string.preparation))
        timeDescBuilder.append(" ")
        if (detail.recipe.prepareHours.isPositive()) {
            timeDescBuilder.append(detail.recipe.prepareHours)
            timeDescBuilder.append(getString(R.string.hours))
            timeDescBuilder.append(" ")
        }
        if (detail.recipe.prepareMinutes.isPositive()) {
            timeDescBuilder.append(detail.recipe.prepareMinutes)
            timeDescBuilder.append(getString(R.string.min))
        }
        timeDescBuilder.append("\n")
        timeDescBuilder.append(getString(R.string.ready_in))
        if (detail.recipe.makeHours.isPositive()) {
            timeDescBuilder.append(detail.recipe.makeHours)
            timeDescBuilder.append(getString(R.string.hours))
            timeDescBuilder.append(" ")
        }
        if (detail.recipe.makeMinutes.isPositive()) {
            timeDescBuilder.append(detail.recipe.makeMinutes)
            timeDescBuilder.append(getString(R.string.min))
        }

        binding.tvFoodTime.text = timeDescBuilder.toString()
        binding.tvEasy.text = detail.recipe.difficultyLevel
        binding.startLayout.tvStarNum.text = "(${detail.recipe.useNum})"
        detail.recipe.score?.let { setStarCount(it.toInt()) }
    }

    fun setStarCount(count: Int) {
        var starCount = count
        if (starCount > 5 || starCount < 0) {
            starCount = 0
        }
        when (starCount) {
            1 -> {
                binding.startLayout.ivStar1.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
            }
            2 -> {
                binding.startLayout.ivStar1.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar2.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
            }
            3 -> {
                binding.startLayout.ivStar1.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar2.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar3.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)

            }
            4 -> {
                binding.startLayout.ivStar1.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar2.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar3.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar4.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
            }
            5 -> {
                binding.startLayout.ivStar1.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar2.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar3.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar4.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
                binding.startLayout.ivStar5.setBackgroundResource(com.develop.base.R.drawable.ic_star_selected)
            }
        }

    }



    private fun selectTab(tab: Int) {
        for (tabView in allTabViews) {
            tabView.isSelected = false
        }
        when (tab) {
            TAB_SOURCE -> {
                binding.ivTab1.isSelected = true
                replaceFragmentInstance(R.id.fl_tab_content, CookDetailSourceFragment())
            }
            TAB_DESC -> {
                binding.ivTab2.isSelected = true
                replaceFragmentInstance(R.id.fl_tab_content, CookDetailDescFragment())
            }
            TAB_TOOLS -> {
                binding.ivTab3.isSelected = true
                replaceFragmentInstance(R.id.fl_tab_content, CookDetailToolsFragment())
            }
            TAB_SERVE -> {
                binding.ivTab4.isSelected = true
                replaceFragmentInstance(R.id.fl_tab_content, CookDetailServeFragment())
            }
        }
    }

    @Suppress("UNCHECKED_CAST")
    private fun updateDownloadButton(resource: Resource<Int>) {
        binding.tvDownload.tag = resource
        if (resource.status == Resource.Status.FAILURE) {
            binding.tvDownload.setVisible()
            binding.viewIcon.setVisible()
            binding.tvProgress.setGone()
            binding.tvDownloadState.setGone()
            binding.tvDownload.text = getString(R.string.download).uppercase(Locale.ROOT)
            binding.viewProgress.setProgress(1f)
            binding.viewProgress.setButtonColor(Color.parseColor("#1296db"))
            binding.viewIcon.setImageResource(R.drawable.ic_detail_cook_download)
            dowloadFialDialog.showDialog(supportFragmentManager,"DownloadFailedDialog")
        } else if (resource.status == Resource.Status.LOADING) {
            val updateProgress = "${resource.data}%"
            binding.tvDownload.setGone()
            binding.viewIcon.setGone()
            binding.tvProgress.setVisible()
            binding.tvDownloadState.setVisible()
            binding.tvProgress.updateText(updateProgress)
            binding.viewProgress.setProgress(resource.data!! / 100f)
            binding.viewProgress.setButtonColor(Color.parseColor("#79C414"))
            binding.viewIcon.setImageResource(R.drawable.ic_detail_cook_download)
        } else {
            binding.tvDownload.setVisible()
            binding.viewIcon.setVisible()
            binding.tvProgress.setGone()
            binding.tvDownloadState.setGone()
            binding.tvDownload.setText(R.string.start_cooking)
            binding.viewProgress.setProgress(1f)
            binding.viewProgress.setButtonColor(Color.RED)
            binding.viewIcon.setImageResource(R.drawable.ic_detail_cook_start)
        }
    }

    override fun onResume() {
        super.onResume()
        viewModel.getStarCount(recipeNumber ?: "")
    }

    private fun selectStar(count: Int) {
        for (index in starViews.indices) {
            starViews[index].isSelected = index + 1 <= count
        }
    }

    private fun showAmountSelectDialog() {
        viewModel.getRecipeLiveData().value?.let {
            AmountSelectDialog(it.portionSize) { size ->
                viewModel.portionSizeLiveData.value = size
            }.showDialog(supportFragmentManager, "AmountSelectDialog")
        }
    }

    private fun showDeleteRecipeDialog() {
        val dialog = RecipeDeleteConfirmDialog {
            ThreadUtils.runOnWorkThread({
                val recipe = viewModel.getRecipeLiveData().value?.recipe
                if (recipe != null) {
                    FoodDataProvider.getDatabase().recipeDao().deleteRecipe(recipe)
                    FoodDataProvider.deleteRecipeResource(recipe.number ?: "")
                    FoodDataProvider.getUserDatabase().userInfoDao()
                        .removeOnlineRecipe(
                            CURRENT_USER_ID, recipe.number ?: ""
                        )
                    runOnUiThread {
                        finish()
                    }
                }
            })
        }
        dialog.showDialog(supportFragmentManager,"RecipeDeleteConfirmDialog")
    }

    override fun createViewBinding(inflater: LayoutInflater): ActivityCookDetailBinding {
        return ActivityCookDetailBinding.inflate(inflater)
    }

    companion object {
        private const val TAB_SOURCE = 1
        private const val TAB_DESC = 2
        private const val TAB_TOOLS = 3
        private const val TAB_SERVE = 4
    }
}