package com.seatel.mobilehall.ui.home.fragment

import android.annotation.SuppressLint
import android.graphics.drawable.ColorDrawable
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.Request
import com.android.volley.VolleyError
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.seatel.mobilehall.R
import com.seatel.mobilehall.data.network.SeatelJSONArrayRequest
import com.seatel.mobilehall.data.network.SeatelSuperRequest
import com.seatel.mobilehall.data.prefs.SeatelSharePreferences
import com.seatel.mobilehall.ui.base.adapter.BaseListFragment
import com.seatel.mobilehall.ui.base.adapter.BaseRecyclerAdapter
import com.seatel.mobilehall.ui.home.activity.BuyYesNumberPhaseTopUpActivity
import com.seatel.mobilehall.ui.home.activity.LocationShopMapActivity
import com.seatel.mobilehall.ui.home.adapter.FullNumberAdapter
import com.seatel.mobilehall.ui.home.adapter.SimPriceAdapter
import com.seatel.mobilehall.ui.home.interactor.BuyYesSimCardInteractor
import com.seatel.mobilehall.ui.home.model.SimCardPriceModel
import com.seatel.mobilehall.ui.home.model.SimCardPricePurchaseAbleModel
import com.seatel.mobilehall.ui.home.model.YesNumberApiData
import com.seatel.mobilehall.ui.home.model.YesNumberModel
import com.seatel.mobilehall.ui.home.presenter.BuyYesSimCardPresenter
import com.seatel.mobilehall.util.AnimationUtil
import com.seatel.mobilehall.util.SeatelAlertDialog
import com.seatel.mobilehall.util.SeatelUtils
import com.seatel.mobilehall.util.customview.ErrorHandleView
import kotlinx.android.synthetic.main.fragment_full_number.*
import kotlinx.android.synthetic.main.item_buy_yes_number.*
import kotlinx.android.synthetic.main.layout_bottom_sheet_buy_yes_number_next.*
import kotlinx.android.synthetic.main.layout_default_error.*
import org.json.JSONArray

/**
 *
 *
 * @author Noel
 * @version
 * @created on 19-Oct-18
 */
abstract class BaseBuySimFragment : BaseListFragment(), BuyYesSimCardInteractor.View,
    BaseRecyclerAdapter.OnItemClickListener<YesNumberModel> {

    private var mBottomSheetPriceRangeDialog: BottomSheetDialog? = null
    private var mDatas: ArrayList<YesNumberModel> = ArrayList()
    protected var buyYesSimCardPresenter: BuyYesSimCardPresenter? = null
    protected var startPrice: Int? = null
    protected var endPrice: Int? = null
    protected var lastSelectModel: YesNumberModel? = null
    private var simPriceAdapter: SimPriceAdapter? = null
    protected var bottomSheetBehavior: BottomSheetBehavior<LinearLayout>? = null
    private var mSimPriceModels = ArrayList<SimCardPriceModel>()
    private var mSimPricePurchaseAbleModels = ArrayList<SimCardPricePurchaseAbleModel>()
    private var isPurchasable = true

    override fun initLayoutManager(): RecyclerView.LayoutManager {
        return LinearLayoutManager(context)
    }

    override fun initAdapter(): RecyclerView.Adapter<RecyclerView.ViewHolder> {
        return FullNumberAdapter(requireContext(), mDatas).apply {
            this.limit = this@BaseBuySimFragment.limit()
        }
    }

    override fun init() {
        super.init()
        mRecyclerView?.itemAnimator = null
        buyYesSimCardPresenter = BuyYesSimCardPresenter(this)
        initNextBottomSheet()
    }

    protected open fun getIsWinPromotionFreeSim(): Boolean {
        return false
    }

    protected open fun initNextBottomSheet() {
        bottomSheetBehavior = BottomSheetBehavior.from(layout_bottom_sheet)
        bottomSheetBehavior?.isHideable = true
        bottomSheetBehavior?.state = BottomSheetBehavior.STATE_HIDDEN
    }

    private fun setPurchaseAbleData() {
        if (mSimPricePurchaseAbleModels.isEmpty()) {
            mSimPricePurchaseAbleModels = ArrayList()
            for (i in 0 until mSimPriceModels.size) {
                mSimPricePurchaseAbleModels.add(
                    SimCardPricePurchaseAbleModel(
                        mSimPriceModels[i].isPurchasable,
                        mSimPriceModels[i].amount
                    )
                )
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        buyYesSimCardPresenter?.onDestroy()
    }

    override fun initEvent() {
        super.initEvent()
        val turnsType = object : TypeToken<ArrayList<SimCardPriceModel>>() {}.type
        val dataFilter =
            SeatelSharePreferences.getInstance(getmContext())?.getPhoneFilterCategories()
        if (dataFilter?.isNotEmpty()!!)
            mSimPriceModels = Gson().fromJson(dataFilter, turnsType)
        if (mSimPriceModels.isEmpty())
            getPhoneFilterCategories()
        layout_show_all.setOnClickListener { showBottomSheetPriceRange() }
        (mAdapter as FullNumberAdapter).onItemClickListener = this
        button_next.setOnClickListener {
            onButtonNextClick()
        }
    }

    private fun getPhoneFilterCategories() {
        object : SeatelJSONArrayRequest(getmContext()) {

            override fun getFunctionName(): String {
                return "seatel/phone-numbers/categories"
            }

            override fun getMethod(): Int {
                return Request.Method.GET
            }

        }.execute {
            it as JSONArray
            if (it.length() > 0) {
                mSimPriceModels = ArrayList()
                for (i in 0 until it.length()) {
                    val startPrice = it.optJSONObject(i).optInt("startPrice", 0)
                    val endPrice = it.optJSONObject(i).optInt("endPrice", 0)
                    val name = it.optJSONObject(i).optString("name", "")
                    val amount = it.optJSONObject(i).optInt("amount", 0)
                    val purchasable = it.optJSONObject(i).optBoolean("purchasable", false)
                    mSimPriceModels.add(
                        SimCardPriceModel(
                            startPrice,
                            endPrice,
                            name,
                            purchasable,
                            amount
                        )
                    )
                }
                SeatelSharePreferences.getInstance(getmContext())?.setPhoneFilterCategories(
                    Gson().toJson(mSimPriceModels)
                )
                setPurchaseAbleData()
            }
        }
    }

    open fun getClaimFreeSim(): Boolean {
        return false
    }

    private fun onButtonNextClick() {
        if (lastSelectModel != null) {
            var priceSim = lastSelectModel!!.price
            if (lastSelectModel!!.discountRate > 0.0)
                priceSim = lastSelectModel!!.discountedPrice
            BuyYesNumberPhaseTopUpActivity.launch(
                requireActivity(),
                lastSelectModel?.phoneNumber!!,
                priceSim,
                lastSelectModel?.cardPrice!!,
                getClaimFreeSim(),
                getIsWinPromotionFreeSim(),
                lastSelectModel?.skipTopUp!!
            )
        }
    }

    private fun isPurchaseAble(price: Double): SimCardPricePurchaseAbleModel {
        for (c in mSimPricePurchaseAbleModels) {
            if (c.amount.toDouble() == price && c.amount > 0)
                return c
        }
        val default = SimCardPricePurchaseAbleModel()
        default.isPurchasable = true
        return default
    }

    override fun onItemClick(v: View, position: Int, data: YesNumberModel) {
        if (!isPurchaseAble(data.price).isPurchasable) {
            LocationShopMapActivity.lunch(context)
        } else {
            val newIndex = mDatas.indexOf(data)
            if (lastSelectModel == null) {
                lastSelectModel = data
                if (newIndex != -1)
                    mDatas[newIndex].isChecked = true
            } else {
                val lastIndex = mDatas.indexOf(lastSelectModel!!)
                if (lastIndex == newIndex) {
                    mDatas[newIndex].isChecked = false
                    lastSelectModel = null
                } else {
                    lastSelectModel = data
                    mDatas[lastIndex].isChecked = false
                    mDatas[newIndex].isChecked = true
                }
            }
            updateUiAfterItemSelected()
            mAdapter.notifyDataSetChanged()
        }
    }

    open fun updateUiAfterItemSelected() {
        showHideBottomSheet(lastSelectModel == null)
    }

    private fun showHideBottomSheet(isHide: Boolean) {
        if (isHide) {
            bottomSheetBehavior?.isHideable = true
            bottomSheetBehavior?.state = BottomSheetBehavior.STATE_HIDDEN
        } else {
            bottomSheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
            bottomSheetBehavior?.isHideable = false
        }
    }

    override fun loadMore() {
        searchPhoneNumber()
    }

    protected open fun searchPhoneNumber() {
        if (!TextUtils.isEmpty(full_name_search.text.toString())) {
            AnimationUtil.instance?.collapse(layout_keyboard)
            buyYesSimCardPresenter?.onSearchPhoneNumber(
                requireContext(),
                full_name_search.text.toString(),
                false,
                startPrice,
                endPrice,
                limit(),
                offset
            )
        }
    }


    @SuppressLint("InflateParams")
    private fun showBottomSheetPriceRange() {

        mBottomSheetPriceRangeDialog = BottomSheetDialog(requireContext(), R.style.CustomDialog)
        mBottomSheetPriceRangeDialog?.window!!.setBackgroundDrawable(
            ColorDrawable(
                ContextCompat.getColor(
                    requireContext(),
                    android.R.color.transparent
                )
            )
        )
        mBottomSheetPriceRangeDialog?.window!!.setGravity(Gravity.BOTTOM)
        mBottomSheetPriceRangeDialog?.window!!.setDimAmount(0.5f)
        mBottomSheetPriceRangeDialog?.window!!.attributes.windowAnimations =
            R.style.DialogAnimationSlideUpDown
        val sheetView =
            requireActivity().layoutInflater.inflate(R.layout.fragment_bottom_sheet, null)
        val recyclerView = sheetView.findViewById<RecyclerView>(R.id.recycler_sim_price)
        val buttonLogin = sheetView.findViewById<Button>(R.id.button_login)
        buttonLogin.setOnClickListener { mBottomSheetPriceRangeDialog?.dismiss() }
        setSimPriceRecycler(recyclerView)
        mBottomSheetPriceRangeDialog?.setContentView(sheetView)
        mBottomSheetPriceRangeDialog?.show()
    }


    private fun setSimPriceRecycler(recyclerView: RecyclerView) {
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = LinearLayoutManager(context)
        if (simPriceAdapter == null) {
            simPriceAdapter = SimPriceAdapter(simCardPriceItems())
        }
        recyclerView.adapter = simPriceAdapter
        simPriceAdapter?.onItemClickListener =
            object : BaseRecyclerAdapter.OnItemClickListener<SimCardPriceModel> {
                override fun onItemClick(v: View, position: Int, data: SimCardPriceModel) {
                    onItemSimCardPriceClick(data)
                }
            }
    }

    private fun onItemSimCardPriceClick(data: SimCardPriceModel) {
        clearDataNotify()
//        if (data.startPrice != data.endPrice) {
//            startPrice = null
//            endPrice = null
//        } else {
        startPrice = data.startPrice
        endPrice = data.endPrice
        if (startPrice!! > endPrice!!)
            startPrice = endPrice
//        }
        mBottomSheetPriceRangeDialog?.dismiss()
        lastSelectModel = null
        updateUiAfterItemSelected()
        searchPhoneNumber()
        val name = SeatelUtils.translatForDialog(getmContext(), data.name)
        var strRang = "$name - $${data.startPrice}"
        if (data.endPrice != data.startPrice)
            strRang = data.name

//        val rang = AppUtils.getTitle(data)
//        var strRang = "${rang.first} - ${rang.second}"
//        if (rang.second.isEmpty())
//            strRang = "${rang.first}"
        buy_yes_number_show_all.text = strRang
    }

    private fun simCardPriceItems(): List<SimCardPriceModel> {
        if (mSimPriceModels.isEmpty()) {
            val turnsType = object : TypeToken<ArrayList<SimCardPriceModel>>() {}.type
            val dataFilter =
                SeatelSharePreferences.getInstance(getmContext())?.getPhoneFilterCategories()
            if (dataFilter!!.isNotEmpty())
                mSimPriceModels =
                    Gson().fromJson<ArrayList<SimCardPriceModel>>(dataFilter, turnsType)
            if (mSimPriceModels.isEmpty()) {
                mSimPriceModels = ArrayList()
                mSimPriceModels.add(SimCardPriceModel(0, 500, "Show All", true))
                mSimPriceModels.add(SimCardPriceModel(0, 0, "Standard", true))
                mSimPriceModels.add(SimCardPriceModel(25, 25, "One Star", true))
                mSimPriceModels.add(SimCardPriceModel(50, 50, "Two Stars", true))
                mSimPriceModels.add(SimCardPriceModel(100, 100, "Three Stars", true))
                mSimPriceModels.add(SimCardPriceModel(250, 250, "Four Stars", false))
                mSimPriceModels.add(SimCardPriceModel(500, 500, "Five Stars", false))
            }
        }
        setPurchaseAbleData()
        return mSimPriceModels
    }

    protected fun clearDataNotify() {
        mDatas.clear()
        mAdapter.notifyDataSetChanged()
        returnDefaultLimitOffset()
        item_yes_number.visibility = View.GONE
    }

    override fun showWaiting() {
        super.showWaiting()
        error_view.visibility = View.VISIBLE
        error_view.setViewMode(ErrorHandleView.Mode.LOADING)
    }

    override fun hideWaiting() {
        super.hideWaiting()
        error_view.visibility = View.GONE
    }

    override fun showSearchPhoneNumberFailed(throwable: VolleyError) {
        loading = false
        SeatelAlertDialog.with(requireContext(), SeatelSuperRequest.getErrorMessageFrom(throwable))
            .show()
    }

    @SuppressLint("SetTextI18n")
    override fun showSearchPhoneNumberSuccess(data: YesNumberApiData?) {
        lastSelectModel = null
        onGetDataSuccess(data, false)
    }

    override fun showSearchMorePhoneNumberFailed(throwable: VolleyError) {
        super.showSearchMorePhoneNumberFailed(throwable)
        loading = false
        SeatelAlertDialog.with(requireContext(), SeatelSuperRequest.getErrorMessageFrom(throwable))
            .show()
    }


    @SuppressLint("SetTextI18n")
    override fun showSearchMorePhoneNumberSuccess(data: YesNumberApiData?) {
        onGetDataSuccess(data, true)
    }

    @SuppressLint("SetTextI18n")
    private fun onGetDataSuccess(data: YesNumberApiData?, isMore: Boolean) {
        loading = false
        if (data?.data != null) {
            if (!isMore) {
                mDatas.clear()
                updateView(data)
            }
            val start = mDatas.size - 1
            mDatas.addAll(data.data!!)
            isAllLoadedItem = data.data!!.size < limit()
            (mAdapter as FullNumberAdapter).isLoadAll = isAllLoadedItem
            (mAdapter as FullNumberAdapter).mSimPricePurchaseAbleModels =
                mSimPricePurchaseAbleModels
            if (!isMore) {
                mAdapter.notifyDataSetChanged()
            } else {
                mAdapter.notifyItemRangeInserted(start, data.data!!.size + 1)
            }
            offset += data.data!!.size
            if (data.metadata != null) {
                text_view_total.text = " : ${data.metadata!!.total}"
            }
        }
    }

    private fun updateView(data: YesNumberApiData) {
        item_yes_number.visibility = View.VISIBLE
        if (data.data != null) {
            if (data.data!!.isEmpty()) {
                error_view.visibility = View.VISIBLE
                error_view.errorMessage = getString(R.string.no_phone_number_data)
                error_view.setViewMode(ErrorHandleView.Mode.NO_DATA)
                return
            }
        }
        error_view.visibility = View.GONE
    }
}