package com.seatel.mobilehall.ui.login.fragment

import android.content.Context
import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.text.TextUtils
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import android.widget.TextView
import com.android.volley.Request
import com.android.volley.VolleyError
import com.google.gson.Gson
import com.seatel.mobilehall.R
import com.seatel.mobilehall.data.network.SeatelJSONObjectRequest
import com.seatel.mobilehall.data.network.SeatelSuperRequest.getErrorMessageFrom
import com.seatel.mobilehall.data.prefs.SeatelSharePreferences
import com.seatel.mobilehall.databinding.FragmentConfirmationBinding
import com.seatel.mobilehall.ui.application.MyApplication
import com.seatel.mobilehall.ui.login.activity.LoginActivity
import com.seatel.mobilehall.ui.login.activity.UpdatedSimProfileActivity
import com.seatel.mobilehall.ui.login.interactor.ConfirmSignUpInteractor
import com.seatel.mobilehall.ui.login.interactor.SignUpInteractor
import com.seatel.mobilehall.ui.login.model.ProfileModel
import com.seatel.mobilehall.ui.login.model.ResetPasswordModel
import com.seatel.mobilehall.ui.login.presenter.ConfirmSignUpPresenter
import com.seatel.mobilehall.ui.login.presenter.SignUpPresenter
import com.seatel.mobilehall.util.AnimationUtil
import com.seatel.mobilehall.util.Constant
import com.seatel.mobilehall.util.SeatelAlertDialog
import com.seatel.mobilehall.util.SeatelUtils
import com.seatel.mobilehall.util.customview.CustomEditText
import com.seatel.mobilehall.util.customview.CustomKeyboard
import com.seatel.mobilehall.util.customview.ErrorHandleView
import com.seatel.mobilehall.util.interactor.KeyBoardNumberInteractor
import com.seatel.mobilehall.util.manager.OrderingManager
import org.json.JSONObject
import java.util.Locale

open class ConfirmationFragment : MainFragment(), KeyBoardNumberInteractor,
    ConfirmSignUpInteractor.View, SignUpInteractor.View, View.OnTouchListener {

    private var _binding: FragmentConfirmationBinding? = null
    private val binding get() = _binding!!

    private val OFFSET = 100
    private var mHiddenTextView: TextView? = null
    private val mEditTexts = ArrayList<CustomEditText>()
    private var mConfirmUserPresenter: ConfirmSignUpPresenter? = null
    private var mSignUpPresenter: SignUpPresenter? = null
    private lateinit var keyBoardNumberView: CustomKeyboard
    private var mPhone: String = ""
    private var mEmail: String = ""
    private var mPassword: String = ""
    private var mTypeRegister: String = ""
    private var mSocialType: String = ""
    private var mMainPhoneNumber = ""
    private lateinit var timerResend: CountDownTimer
    private var isCanceled = false
    var isRequesting = false
    private var handlerSMS: Handler? = null
    private var dialogAlert: SeatelAlertDialog? = null


    fun setDataPost(
        mPhone: String,
        mEmail: String,
        mPassword: String,
        mSocialType: String,
        mTypeRegister: String
    ) {
        this.mPhone = mPhone
        this.mEmail = mEmail
        this.mPassword = mPassword
        this.mTypeRegister = mTypeRegister
        this.mSocialType = mSocialType
    }

    fun setDataForAddPhoneNumber(phone: String) {
        this.mMainPhoneNumber = phone
    }

    fun isFeatureAddNewPhone(): Boolean {
        return mMainPhoneNumber.isNotEmpty()
    }

    fun getMainPhone(): String {
        return mMainPhoneNumber
    }

    fun getPhone(): String {
        return mPhone
    }

    fun getTypeConfirm(): String {
        return mTypeRegister
    }

    private fun showScreenNext(offnetNumber: Boolean) {

        if (TextUtils.equals(
                mTypeRegister,
                Constant.REGISTER
            ) or (TextUtils.equals(mTypeRegister, Constant.SOCIAL_REGISTER))
        ) {
            cancelRuningTimer()
            // Show Home screen
            SeatelSharePreferences.getInstance(getmContext())
                ?.setNoneSeatelNumber(offnetNumber) //SeatelUtils.checkIsNonSeatel(mPhone)
            SeatelSharePreferences.getInstance(getmContext())?.setPhoneLogin(mPhone)
            SeatelSharePreferences.getInstance(getmContext())?.setMainPhoneLogin(mPhone)
            SeatelUtils.gotoMainScreen(context)
            getMainActivity().closeHome()
            SeatelUtils.hideKeyboard(getmContext() as LoginActivity)
            SeatelSharePreferences.getInstance(requireContext())?.setLoginSuccess("true")
            binding.keyboardView.hideKeyBoard()

        }
    }

    override fun onDestroy() {
        super.onDestroy()
        mConfirmUserPresenter?.onDestroy()
        mSignUpPresenter?.onDestroy()
    }

    override fun onConfirmSucceed() {
        binding.errorView.visibility = View.GONE
        cancelRuningTimer()
        when {
            getTypeConfirm().equals(Constant.VERRIFY_PHONE_NUMBER, true) -> {
                UpdatedSimProfileActivity.launch(getmContext(), mPhone)
                dialogAlert?.dimissDialog()
                getMainActivity().finish()
                return
            }

            isFeatureAddNewPhone() -> {
                MyApplication.isAddnewNumberDone = true
                SeatelSharePreferences.getInstance(getmContext())?.setPhoneLogin(mPhone)
                getMainActivity().closeHome()
                SeatelUtils.hideKeyboard(getmContext() as LoginActivity)
                binding.keyboardView.hideKeyBoard()
                return
            }

            else -> getProfileData()
        }
        isRequesting = false
        binding.buttonConfirm.isEnabled = true

    }

    private fun getProfileData() {
        object : SeatelJSONObjectRequest(getmContext()) {

            override fun getFunctionName(): String {
                return "v2/seatel/profile?phoneNumber=${getPhone()}"
            }

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

        }.setOnErrorListener { _ ->
            SeatelAlertDialog.with(getmContext(), getString(R.string.register_success))
                .setPositiveButton(getString(R.string.yes)) { _, _ ->
                    showScreenNext(SeatelUtils.checkIsNonSeatel(mPhone))
                }.show()
        }.execute {
            it as JSONObject
            val profileModel = ProfileModel()
            profileModel.certType = it.optString("certType")
            profileModel.certNumber = it.optString("certNumber")
            profileModel.custName = it.optString("custName")
            profileModel.msisdn = it.optString("mSISDN")
            profileModel.email = it.optString("email")
            profileModel.imageUrl = it.optString("profilePicture")
            profileModel.isOffnetNumber =
                SeatelUtils.checkIsNoneSeatelType(it.optString("type", ""))
            profileModel.isSnowfall = it.optBoolean("snowfall", false)
            if (it.has("orderIds")) {
                val dataId = it.optJSONArray("orderIds")
                val idList: ArrayList<Int> = ArrayList()
                for (i in 0..(dataId.length() - 1)) {
                    idList.add(dataId.optInt(i))
                }
                profileModel.orderIdUnSuccess = idList
            }
            if (it.has("shipmentInsuranceRate"))
                OrderingManager.getInstance().shipmentInsuranceRate =
                    it.optDouble("shipmentInsuranceRate", 0.0)
            SeatelSharePreferences.getInstance(getmContext())
                ?.setUserInfo(Gson().toJson(profileModel))
            SeatelAlertDialog.with(getmContext(), getString(R.string.register_success))
                .setPositiveButton(getString(R.string.yes)) { _, _ ->
                    showScreenNext(profileModel.isOffnetNumber)
                }.show()
        }
    }

    override fun onConfirmFailed(error: VolleyError) {
        if (binding.errorView != null) {
            isRequesting = false
            binding.errorView.visibility = View.GONE
            dialogAlert?.dimissDialog()
            dialogAlert =
                SeatelAlertDialog.with(getMainActivity(), getErrorMessageFrom(error)).show()
            resetCodeInput()
            binding.buttonConfirm.isEnabled = true

//            if (getHomeActivity() != null) {
//                getHomeActivity().startSMSService()
//            }
        }
    }

    override fun onRequestCodeSucceed(resetPasswordModel: ResetPasswordModel) {
        if (binding.errorView != null) {
            isRequesting = false
            binding.errorView.visibility = View.GONE
            startResendCountDown()
            binding.tvResendCodeConfirm.isEnabled = true
        }
    }

    override fun onRequestCodeFailed(error: VolleyError) {
        isRequesting = false
        binding.errorView.visibility = View.GONE
        SeatelAlertDialog.with(requireContext(), getErrorMessageFrom(error)).show()
        binding.tvResendCodeConfirm.isEnabled = true
    }


    override fun onAttach(context: Context) {
        super.onAttach(context)
        setmContext(context)
        setActivity(context as LoginActivity)
        // setFragmentLayout(R.layout.fragment_confirmation)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        _binding = FragmentConfirmationBinding.bind(view)
        mConfirmUserPresenter = ConfirmSignUpPresenter(getmContext(), this)
        mSignUpPresenter = SignUpPresenter(getmContext(), this)
        init()
    }

    override fun getFragmentOffset(): Int {
        return OFFSET
    }

    override fun onKeyBoardKeyClick(key: String) {
        onInsert(key)
    }

    override fun onKeyBoardKeyClearClick() {
        onClear()
    }

    private fun startConfirmCode() {
        if (isRequesting) return
        val codeConfirm = binding.textViewHidden.text.toString().trim()
        if (TextUtils.isEmpty(codeConfirm) || codeConfirm.length < 6) {
            SeatelAlertDialog.with(requireContext(), getString(R.string.enter_confirmation)).show()
            return
        }
        binding.buttonConfirm.isEnabled = false
        isRequesting = true
        binding.errorView.setViewMode(ErrorHandleView.Mode.LOADING)
        dialogAlert?.dimissDialog()
        mConfirmUserPresenter?.onConfirmCode(
            "v2/",
            codeConfirm,
            mEmail,
            "",
            mPhone,
            mPassword,
            mSocialType,
            mTypeRegister
        )
//        cancelRuningTimer()
    }

    fun startResendCountDown() {
        binding.tvResendCodeConfirm.visibility = View.GONE
        binding.layoutActionCodeSent.visibility = View.VISIBLE

        timerResend = object : CountDownTimer(120000, 1000) {
            override fun onTick(millisUntilFinished: Long) {
                if (isCanceled) {
                    timerResend.cancel()
                    return
                }
                if (binding.tvConfirmCodeSent != null) {
                    binding.tvConfirmCodeSent.text = String.format(
                        Locale.US, "%s",
                        SeatelUtils.milliSecondsToTimer(millisUntilFinished)
                    )
                }
            }

            override fun onFinish() {
                if (binding.tvResendCodeConfirm != null) {
                    binding.tvResendCodeConfirm.visibility = View.VISIBLE
                    binding.layoutActionCodeSent.visibility = View.GONE
                }
            }
        }.start()
    }

    private fun onEditTextSearchTouch() {
        AnimationUtil.instance?.expand(binding.layoutKeyboard)
    }

    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
        if (v != null)
            when (v.id) {
                R.id.edit_text_confirm_code_one, R.id.edit_text_confirm_code_two, R.id.edit_text_confirm_code_three, R.id.edit_text_confirm_code_four,
                R.id.edit_text_confirm_code_five, R.id.edit_text_confirm_code_six -> {
                    onEditTextSearchTouch()
                }
            }
        return false
    }

    private fun init() {

        startResendCountDown()
        binding.buttonConfirm.setOnClickListener {
            AnimationUtil.instance?.collapse(binding.layoutKeyboard)
            startConfirmCode()
        }

//        getHomeActivity().setFilterSMS(SeatelUtils.checkIsNonSeatel(mPhone))
        binding.tvResendCodeConfirm.setOnClickListener {
            binding.errorView.setViewMode(ErrorHandleView.Mode.LOADING)
            resetCodeInput()
            onEditTextSearchTouch()
            startResendCountDown()
            isRequesting = true
            binding.tvResendCodeConfirm.isEnabled = false
            mSignUpPresenter?.onRequestCode(mPhone, mEmail, mTypeRegister, "", "")
        }
        binding.imageViewBack.setOnClickListener { onBackPress() }
        keyBoardNumberView = binding.keyboardView
        keyBoardNumberView.setKeyBoardNumberInteractor(this)
        keyBoardNumberView.showKeyBoard()
        mEditTexts.add(binding.editTextConfirmCodeOne)
        mEditTexts.add(binding.editTextConfirmCodeTwo)
        mEditTexts.add(binding.editTextConfirmCodeThree)
        mEditTexts.add(binding.editTextConfirmCodeFour)
        mEditTexts.add(binding.editTextConfirmCodeFive)
        mEditTexts.add(binding.editTextConfirmCodeSix)

        for (editText in mEditTexts) setEditTextTouchListener(editText)

        mEditTexts[0].requestFocus()
        mHiddenTextView = binding.textViewHidden
    }

    private fun setEditTextTouchListener(textEdit: EditText) {
        textEdit.setOnTouchListener(this)
        textEdit.showSoftInputOnFocus = false
    }

    private fun onInsert(key: String) {

        if (mHiddenTextView!!.text.length == mEditTexts.size) return
        val pos = getInsertPos(key)
        val textView = mEditTexts[pos]

        textView.setText(key)
//        textView.transformationMethod = HideReturnsTransformationMethod.getInstance()
//        textView.postDelayed(object : Runnable {
//            override fun run() {
//                textView.transformationMethod = PasswordTransformationMethod.getInstance()
//                textView.removeCallbacks(this)
//            }
//        }, 200)

        textView.isCursorVisible = false
        if (pos == mEditTexts.size - 1) return
        mEditTexts[pos + 1].requestFocus()
    }

    fun resetCodeInput() {
        binding.textViewHidden.text = ""
        val length = mEditTexts.size - 1
        for (i in 0..length) {
            mEditTexts[i].setText("")
        }
        mEditTexts[0].requestFocus()
        mEditTexts[0].isCursorVisible = true
    }

    private fun onClear() {
        if (mHiddenTextView!!.text.isEmpty()) return
        val pos = getClearPos()
        mEditTexts[pos].requestFocus()
        mEditTexts[pos].isCursorVisible = true
        mEditTexts[pos].setText("")
    }

    fun cancelRuningTimer() {
        isCanceled = true
        timerResend.cancel()
    }

    override fun onBackPress() {
        super.onBackPress()
        cancelRuningTimer()
        getmMainFragmentPresenter()!!.addFragment(SignUpFragment(), true)
    }

    private fun getInsertPos(key: String): Int {
        mHiddenTextView!!.text = mHiddenTextView!!.text.toString() + key
        return mHiddenTextView!!.text.length - 1
    }

    private fun getClearPos(): Int {
        mHiddenTextView!!.text =
            mHiddenTextView!!.text.subSequence(0, mHiddenTextView!!.length() - 1)
        return mHiddenTextView!!.text.length
    }

    fun smsResponse(body: String, sender: String) {
        if (sender == Constant.SENDER_NUMBER || sender == Constant.SENDER_NUMBER_OFFNET) {
            val code = body.split(": ")[1].replace(".", "")
            code(code)
        }
    }

    fun smsReceiver(body: String) {
        code(body)
    }

    open fun code(code: String) {
        if (TextUtils.isEmpty(code)) {
            SeatelAlertDialog.with(requireContext(), getString(R.string.enter_confirmation)).show()
            return
        }
        mHiddenTextView!!.text = code
        val chars = code.toCharArray()
        for ((i, char) in chars.withIndex()) {
            mEditTexts[i].setText(char.toString())
            if (i == 0) mEditTexts[i].isCursorVisible = false
        }

        handlerSMS = Handler()
        handlerSMS?.postDelayed({
            if (binding.buttonConfirm != null)
                binding.buttonConfirm.callOnClick()
        }, 0)
    }

}