package com.abbidot.tracker.util

import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.TimeInterpolator
import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.graphics.Rect
import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.StateListDrawable
import android.os.Build
import android.text.InputFilter
import android.text.InputType
import android.text.TextUtils
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.CompoundButton
import android.widget.DatePicker
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.NumberPicker
import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.core.animation.doOnCancel
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import coil.load
import coil.transform.Transformation
import com.abbidot.baselibrary.constant.ConState
import com.abbidot.baselibrary.constant.MMKVKey
import com.abbidot.baselibrary.list.BaseRecyclerAdapter
import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.LogUtil
import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.baselibrary.util.Utils
import com.abbidot.tracker.R
import com.abbidot.tracker.adapter.GridItemDecoration
import com.abbidot.tracker.adapter.SelectMapTypeCardShadeAdapter
import com.abbidot.tracker.adapter.SpaceItemDecoration
import com.abbidot.tracker.base.BaseActivity
import com.abbidot.tracker.base.BaseDialog
import com.abbidot.tracker.bean.DataBean
import com.abbidot.tracker.bean.MenuTxtBean
import com.abbidot.tracker.bean.PetBean
import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.constant.GetResultCallback
import com.abbidot.tracker.constant.MultipleEntity
import com.abbidot.tracker.dialog.MyAlertDialog
import com.abbidot.tracker.dialog.SelectMapTypeDialog
import com.abbidot.tracker.ui.activity.WebViewActivity
import com.abbidot.tracker.widget.TypefaceTextView
import com.daimajia.androidanimations.library.Techniques
import com.daimajia.androidanimations.library.YoYo
import com.daimajia.androidanimations.library.YoYo.YoYoString
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.hjq.permissions.XXPermissions
import com.hjq.permissions.permission.PermissionLists
import com.hjq.toast.Toaster
import com.huantansheng.easyphotos.EasyPhotos
import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton
import com.qmuiteam.qmui.util.QMUIDisplayHelper
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet.BottomListSheetBuilder
import com.qmuiteam.qmui.widget.grouplist.QMUICommonListItemView
import java.util.Calendar


/**
 *Created  by .yzq on 2021/12/22/022.
 * @link
 * @description:
 */
class ViewUtil private constructor() {

    //单例模式
    companion object {
        //粗体字体
        const val FONT_BOLD = "fonts/Roboto_Bold.ttf"
        const val FONT_BOLD_NAME = "roboto_bold_font"

        //普通黑色字体
        const val FONT_COMMON = "fonts/Roboto_Regular.ttf"
        const val FONT_COMMON_NAME = "roboto_regular_font"

        //数字字体
        const val FONT_NUMBER = "fonts/DinCond_Bold.otf"
        const val FONT_NUMBER_NAME = "number_din_cond_font"

        //信用卡字体
        const val FONT_CREDIT = "fonts/Credit.ttf"
        const val FONT_CREDIT_NAME = "credit_card_font"

        const val textImageUrl =
            "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.zhimg.com%2Fv2-087b76d6a57befbf484e3aa8138037fa_1440w.jpg%3Fsource%3D172ae18b&refer=http%3A%2F%2Fpic1.zhimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1644660067&t=b8edb5a50920007abdd445d461ff6bab"

        val instance: ViewUtil by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            ViewUtil()
        }
    }

    /**
     * 设置字体
     */
    fun setTypeface(context: Context, type: String?): Typeface {
        //默认字体
        var typeface = Typeface.DEFAULT
        when (type) {
            FONT_BOLD_NAME -> {
                typeface = Typeface.createFromAsset(context.assets, FONT_BOLD)
            }

            FONT_COMMON_NAME -> {
                typeface = Typeface.createFromAsset(context.assets, FONT_COMMON)
            }

            FONT_NUMBER_NAME -> {
                typeface = Typeface.createFromAsset(context.assets, FONT_NUMBER)
            }

            FONT_CREDIT_NAME -> {
                typeface = Typeface.createFromAsset(context.assets, FONT_CREDIT)
            }
        }

        return typeface
    }


    /**
     * 设置QMUICommonListItemView数据,一组多个水平控件的按钮
     *
     * @param name 按钮名字用于左边显示
     * @param accessoryType 右边显示类型
     */
    fun showQMUICommonListItemView(
        context: Context,
        qMUIItemView: QMUICommonListItemView,
        onClickListener: View.OnClickListener?,
        name: String,
        accessoryType: Int
    ) {
        val tf = setTypeface(context, context.getString(R.string.roboto_bold_font))

        qMUIItemView.let {
            it.text = name
            //带有值显示下方，例如详情
            it.orientation = QMUICommonListItemView.HORIZONTAL
            it.textView.typeface = tf
            if (accessoryType != -1) it.accessoryType = accessoryType
            it.detailText = ""
            it.setOnClickListener(onClickListener)
        }
    }

    fun showQMUICommonListItemView(
        context: Context,
        qMUIItemView: QMUICommonListItemView,
        onClickListener: View.OnClickListener?,
        name: String
    ) {
        showQMUICommonListItemView(context, qMUIItemView, onClickListener, name, -1)
    }

    /**
     * 设置NumberPicker相关属性
     */
    fun setNumberPickerAttributes(
        context: Context,
        numberPicker: NumberPicker,
        min: Int = 0,
        max: Int,
        cValue: Int = 0,
        tSize: Int = 0,
        formatter: NumberPicker.Formatter? = null,
        valueChangeListener: NumberPicker.OnValueChangeListener? = null,
        //去掉上下2行线
        removeUpDownLine: Boolean = false,
        loopSelector: Boolean = true
    ) {
        numberPicker.apply {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                selectionDividerHeight = AppUtils.dpToPx(0.5f).toInt()
                if (tSize > 0) {
                    textSize = QMUIDisplayHelper.sp2px(context, tSize).toFloat()
                }
            }
            if (min >= 0) minValue = min
            if (max >= 0) maxValue = max
            if (cValue >= 0) value = cValue
            //不可编辑
            descendantFocusability = NumberPicker.FOCUS_BLOCK_DESCENDANTS
            //是否可以循环滑动
            wrapSelectorWheel = loopSelector
            //去掉上下2行线
            if (removeUpDownLine) showDividers = LinearLayout.SHOW_DIVIDER_NONE
            if (null != formatter) setFormatter(formatter)
            if (null != valueChangeListener) setOnValueChangedListener(valueChangeListener)
        }
    }

    /**
     * 监听2个关联 NumberPicker 不能同时为0,隐藏按钮
     */
    fun numberPickerLinkageValueNo0(cNumberPickerNewVal: Int, linkage: NumberPicker, btn: View) {
        if (cNumberPickerNewVal == 0 && linkage.value == 0) {
            if (btn.visibility == View.VISIBLE) {
                btn.isEnabled = false
                viewHideFadeInAnimation(btn, hideType = View.INVISIBLE)
            }
        } else {
            if (btn.visibility == View.INVISIBLE) {
                btn.isEnabled = true
                viewShowFadeInAnimation(btn)
            }
        }
    }

    /**
     * 设置item分割线和水平线性布局
     */
    fun setRecyclerViewDecorationLinearLayoutManager(
        context: Context, recyclerView: RecyclerView, adapter: RecyclerView.Adapter<*>
    ) {
        recyclerView.let {
            it.layoutManager = LinearLayoutManager(context)
            it.addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
            it.adapter = adapter
        }
    }

    /**
     * 设置垂直滑动布局的RecyclerView
     */
    fun setRecyclerViewVerticalLinearLayout(
        context: Context,
        recyclerView: RecyclerView,
        adapter: RecyclerView.Adapter<*>,
        left: Int = 0,
        right: Int = 0,
        top: Int = 0,
        bottom: Int = 0
    ) {
        recyclerView.let {
            it.layoutManager = LinearLayoutManager(context)
            if (left > 0 || right > 0 || top > 0 || bottom > 0) it.addItemDecoration(
                SpaceItemDecoration(left, right, top, bottom)
            )
            it.adapter = adapter
        }
    }

    /**
     * 设置水平滑动布局的RecyclerView
     */
    fun setRecyclerViewHorizontalLinearLayout(
        context: Context,
        recyclerView: RecyclerView,
        adapter: RecyclerView.Adapter<*>,
        left: Int = 0,
        right: Int = 0,
        top: Int = 0,
        bottom: Int = 0
    ) {
        recyclerView.let {
            it.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
            if (left > 0 || right > 0 || top > 0 || bottom > 0) it.addItemDecoration(object :
                RecyclerView.ItemDecoration() {
                override fun getItemOffsets(
                    outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
                ) {
                    val position = parent.getChildAdapterPosition(view)
                    if (left > 0 && position == 0) {
                        outRect.left = left
                    }
                    if (right > 0) {
                        outRect.right = right
                    }
                    if (top > 0) {
                        outRect.top = top
                    }
                    if (bottom > 0) {
                        outRect.bottom = bottom
                    }
                }
            })
            it.adapter = adapter
        }
    }

    fun setRecyclerViewFlexboxLayout(
        context: Context,
        recyclerView: RecyclerView,
        adapter: RecyclerView.Adapter<*>,
        left: Int = 0,
        right: Int = 0,
        top: Int = 0,
        bottom: Int = 0
    ) {
        recyclerView.let {
            it.layoutManager = FlexboxLayoutManager(context)
            if (left > 0 || right > 0 || top > 0 || bottom > 0) it.addItemDecoration(
                SpaceItemDecoration(left, right, top, bottom)
            )
            it.adapter = adapter
        }
    }

    /**
     * 设置GridLayout布局的RecyclerView
     * @param offset 控件的外边距，不使用屏幕宽度来计算
     */
    fun setRecyclerViewGridLayout(
        context: Context,
        recyclerView: RecyclerView,
        adapter: RecyclerView.Adapter<*>,
        spanCount: Int,
        itemWidth: Int = AppUtils.dpToPx(80),
        top: Int = 0,
        bottom: Int = 0,
        offset: Int = 0
    ) {
        recyclerView.let {
            it.layoutManager = GridLayoutManager(context, spanCount)
            it.addItemDecoration(
                GridItemDecoration(
                    context, spanCount, itemWidth, top, bottom, offset
                )
            )
            it.adapter = adapter
        }
    }

    /**
     * 设置输入框的错误显示
     */
    fun setInputViewErrorShow(
        context: Context, viewGroup: ViewGroup, errorTextView: TextView
    ) {
        viewGroup.apply {
            YoYo.with(Techniques.Shake).onStart {
                background = ContextCompat.getDrawable(
                    context, R.drawable.shape8_red_border_white_bg
                )
                errorTextView.setTextColor(ContextCompat.getColor(context, R.color.red_color2))
                viewShowFadeInAnimation(errorTextView, 800)
            }.duration(50).playOn(this)
        }
    }

    /**
     * 设置输入框的错误隐藏事件
     */
    fun setInputViewErrorHideClick(
        context: Context,
        viewGroup: ViewGroup,
        errorView: View,
        editText: EditText,
        onTextChanged: (s: String) -> Unit = {}
    ) {
        viewGroup.apply {
            editText.addTextChangedListener {
                if (errorView.visibility == View.VISIBLE) {
                    background = ContextCompat.getDrawable(
                        context, R.drawable.shape8_gray_border_white_bg
                    )
                    viewHideFadeInAnimation(errorView, 400)
                }
                onTextChanged(it.toString())
            }
        }
    }

    /**
     *设置地图视图离底部重叠部分
     */
    fun setMapViewBottomMarginOverlap(
        viewGroup: ViewGroup, bottomMargin: Int, overlapSpace: Int
    ) {
        val params = viewGroup.layoutParams
        val space = bottomMargin - overlapSpace
        when (params) {
            is LinearLayout.LayoutParams -> {
                if (params.bottomMargin == space) return
                params.bottomMargin = space
            }

            is RelativeLayout.LayoutParams -> {
                if (params.bottomMargin == space) return
                params.bottomMargin = space
            }

            is FrameLayout.LayoutParams -> {
                if (params.bottomMargin == space) return
                params.bottomMargin = space
            }
        }
        viewGroup.layoutParams = params
    }

    /**
     * 修改shape的圆角半径
     * @param radiusDp 半径大小,dp单位
     */
    fun setShapeRadius(view: View, radiusDp: Int) {
        val stateListDrawable = view.background as StateListDrawable
        val drawable = stateListDrawable.current
        if (drawable is GradientDrawable) {
            drawable.cornerRadius = QMUIDisplayHelper.dpToPx(radiusDp).toFloat()
        }
    }

    /**
     * 显示自定义Dialog
     */
    fun showDialog(
        context: Context,
        contentResId: Int,
        okListener: BaseDialog.OnDialogOkListener,
        title: String = "",
        okTextResId: Int = 0,
        cancelTextResId: Int = 0,
        cancelListener: BaseDialog.OnDialogCancelListener? = null
    ) {
        try {
            showDialog(
                context,
                context.getString(contentResId),
                okListener,
                title,
                okTextResId,
                cancelTextResId,
                cancelListener
            )
        } catch (e: Exception) {
            LogUtil.e("showDialog异常：${e.message}")
        }
    }

    /**
     * 显示自定义Dialog
     */
    fun showDialog(
        context: Context,
        contentResId: String,
        okListener: BaseDialog.OnDialogOkListener,
        title: String = "",
        okTextResId: Int = 0,
        cancelTextResId: Int = 0,
        cancelListener: BaseDialog.OnDialogCancelListener? = null
    ) {
        val myDialog = MyAlertDialog(context)
        myDialog.show()
        myDialog.setTipTitle(title)
        myDialog.setContent(contentResId)
        if (okTextResId != 0) {
            myDialog.setOkText(okTextResId)
        }
        if (cancelTextResId != 0) {
            myDialog.setCancelText(cancelTextResId)
        }
        if (null == cancelListener) {
            myDialog.setOnDialogCancelListener(object : BaseDialog.OnDialogCancelListener {
                override fun onCancelClick(dialog: BaseDialog<*>) {
                    dialog.dismiss()
                }
            })
        } else myDialog.setOnDialogCancelListener(cancelListener)

        myDialog.setOnDialogOkListener(okListener)
    }

    /**
     * 底部弹出菜单
     * @param allowDragDismiss 拖着空白地方可消失
     */
    fun showBottomSheetList(
        context: Context,
        onSheetItemClickListener: BottomListSheetBuilder.OnSheetItemClickListener?,
        title: CharSequence = "",
        gravityCenter: Boolean = true,
        addCancelBtn: Boolean = true,
        allowDragDismiss: Boolean = false
    ): BottomListSheetBuilder {
        val builder = BottomListSheetBuilder(context)
        builder.setGravityCenter(gravityCenter).setAllowDrag(allowDragDismiss)
            .setAddCancelBtn(addCancelBtn).setTitle(title)
            .setCancelText(context.getString(R.string.txt_cancel))
            .setOnSheetItemClickListener(onSheetItemClickListener)
        return builder
    }

    /**
     * 底部弹出界面
     * @param layoutId 要显示的布局
     * @param behaviorState 显示位置。可底部、居中
     */
    fun showBottomSheet(
        context: Context, layoutId: Int, behaviorState: Int = 0
    ): BottomSheetDialog {
        val view = View.inflate(context, layoutId, null)
        val bottomSheetDialog = BottomSheetDialog(context)
        bottomSheetDialog.setContentView(view)
        //改变弹出位置方式
        if (behaviorState > 0) {
            val behavior = BottomSheetBehavior.from(view.parent as View)
            behavior.state = behaviorState
        }
        bottomSheetDialog.show()
        return bottomSheetDialog
    }

    /**
     * 弹出底部日期
     *
     * @param dateList 初始化datePicker显示日期
     * @param getResultCallback 点击ok确定回调
     */
    fun showBottomSheetDate(
        context: Context, dateList: List<String>, getResultCallback: GetResultCallback
    ) {
        val bottomSheetDialog = showBottomSheet(context, R.layout.sheet_dialog_select_date)
        val delegate = bottomSheetDialog.delegate

        val datePicker = delegate.findViewById<DatePicker>(R.id.bottom_sheet_date_picker)
        datePicker!!.maxDate = Calendar.getInstance().timeInMillis

        if (dateList.size > 2) {
            datePicker.updateDate(dateList[0].toInt(), dateList[1].toInt() - 1, dateList[2].toInt())
        }

        delegate.findViewById<TypefaceTextView>(R.id.bottom_sheet_date_ok)!!.setOnClickListener {
            val month = Utils.fill2Digits(datePicker.month + 1)
            val day = Utils.fill2Digits(datePicker.dayOfMonth)
            val birthday = "${datePicker.year}-${month}-${day}"
            getResultCallback.onResult(birthday)
            bottomSheetDialog.dismiss()
        }
        delegate.findViewById<TypefaceTextView>(R.id.bottom_sheet_date_cancel)!!
            .setOnClickListener {
                bottomSheetDialog.dismiss()
            }
    }

    /**
     * 跳转相册和拍照
     * @param count 可以选几张照片
     */
    fun goSelectPhoto(activity: FragmentActivity, requestCode: Int, count: Int = 1) {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)

        XXPermissions.with(activity).permission(PermissionLists.getReadMediaImagesPermission())
            .permission(PermissionLists.getCameraPermission()).request { _, deniedList ->
                val allGranted = deniedList.isEmpty()
                if (allGranted) {
                    LogUtil.e("获取READ_MEDIA_IMAGES权限成功")
                    EasyPhotos.createAlbum(activity, true, false, CoilEngine.instance)
                        .setFileProviderAuthority(FileUtil.FILE_PROVIDER).setCount(count)
                        .setPuzzleMenu(false).setCleanMenu(false).start(requestCode)
                    //activity.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
                } else {
                    val doNotAskAgain =
                        XXPermissions.isDoNotAskAgainPermissions(activity, deniedList)
                    if (doNotAskAgain) {
                        LogUtil.e("READ_MEDIA_IMAGES被永久拒绝授权，请手动授予定位权限")
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(activity, deniedList)
                    } else {
                        LogUtil.e("获取READ_MEDIA_IMAGES权限，但部分权限未正常授予")
                        Toaster.show(R.string.txt_permissions_fail_tips)
                    }
                }

//                override fun onGranted(permissions: MutableList<IPermission>, allGranted: Boolean) {
//                    if (allGranted) {
//                        LogUtil.e("获取READ_MEDIA_IMAGES权限成功")
//                        EasyPhotos.createAlbum(activity, true, false, CoilEngine.instance)
//                            .setFileProviderAuthority(FileUtil.FILE_PROVIDER).setCount(count)
//                            .setPuzzleMenu(false).setCleanMenu(false).start(requestCode)
//                        //activity.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
//                    } else {
//                        LogUtil.e("获取READ_MEDIA_IMAGES权限，但部分权限未正常授予")
//                        Toaster.show(R.string.txt_permissions_fail_tips)
//                    }
//                }
//
//                override fun onDenied(
//                    permissions: MutableList<IPermission>, doNotAskAgain: Boolean
//                ) {
//                    if (doNotAskAgain) {
//                        LogUtil.e("READ_MEDIA_IMAGES被永久拒绝授权，请手动授予定位权限")
//                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
//                        XXPermissions.startPermissionActivity(activity, permissions)
//                    } else {
//                        LogUtil.e("获取READ_MEDIA_IMAGES权限失败")
//                        Toaster.show(R.string.txt_permissions_fail_tips)
//                    }
//                }
            }
    }

    /**
     * coil加载网络图片
     * @param transformations 四种变换：模糊变换（BlurTransformation）、
     * 圆形变换（CircleCropTransformation）、灰度变换（GrayscaleTransformation）
     * 和圆角变换（RoundedCornersTransformation）
     */
    fun imageLoadUrl(
        imageView: ImageView,
        url: String,
        @DrawableRes errorImageResId: Int = R.drawable.icon_placeholder_image_svg,
        vararg transformations: Transformation
    ) {
        imageView.load(url) {
            //placeholder预置展位图
            placeholder(errorImageResId)
            //失败时的错误占位图片
            error(errorImageResId)
            //淡入淡出的动画时间
//            crossfade(2000)
//            memoryCachePolicy(CachePolicy.ENABLED)//设置内存的缓存策略
//            diskCachePolicy(CachePolicy.ENABLED)//设置磁盘的缓存策略
//            networkCachePolicy(CachePolicy.ENABLED)//设置网络的缓存策略
//            OkHttpClient.Builder().cache(CoilUtils.createDefaultCache(context))
            transformations(transformations.toList())
        }
    }


    //属性动画持续时间,首页动画时间
    private val valueAnimatorDuration = 600L

    /**
     * 设置数字变化动画,并设置值
     * @param stringFormat 字符串资源格式
     */
    fun viewNumberValueAnimator(
        view: View,
        startValue: Number,
        endValueAny: Any,
        stringFormat: String = "",
        animatorDuration: Long = valueAnimatorDuration
    ) {
        setValueAnimator(startValue, endValueAny, animatorDuration) {
            if (view is TextView) {
                var str = ""
                when (val value = it.animatedValue) {
                    is Int -> str = value.toString()
                    is Float -> str = Utils.formatDecimal(value, 2)
                    is Double -> str = Utils.formatDecimal(value, 2)
                }
                view.text = if (TextUtils.isEmpty(stringFormat)) str
                else String.format(stringFormat, str)
            } else if (view is ProgressBar) {
                view.progress = it.animatedValue as Int
            }
        }
    }

    /**
     * 设置数值动画
     */
    fun setValueAnimator(
        startValue: Number,
        endValueAny: Any,
        animatorDuration: Long = 1000,
        interpolator: TimeInterpolator = DecelerateInterpolator(), //该插值器的变化率开始很快，然后减速。
        listener: ValueAnimator.AnimatorUpdateListener? = null
    ): ValueAnimator? {
        if (startValue == endValueAny) return null

        var valueAnimator: ValueAnimator? = null
        var endValue = endValueAny

        if (endValueAny is String) {
            endValue = try {
                endValueAny.toInt()
            } catch (e: Exception) {
                endValueAny.toFloat()
            }
        }

        when (endValue) {
            is Int -> valueAnimator = ValueAnimator.ofInt(startValue as Int, endValue)
            is Long -> valueAnimator = ValueAnimator.ofInt(startValue as Int, endValue.toInt())
            is Float -> valueAnimator = ValueAnimator.ofFloat(startValue.toFloat(), endValue)
            is Double -> valueAnimator =
                ValueAnimator.ofFloat(startValue.toFloat(), endValue.toFloat())
        }

        if (null == valueAnimator) return valueAnimator

        valueAnimator.duration = animatorDuration
        valueAnimator.interpolator = interpolator
        listener?.apply {
            valueAnimator.addUpdateListener(this)
        }
        valueAnimator.start()

        return valueAnimator
    }

    /**
     * 围绕自身中心旋转360度、淡化动画
     */
    fun viewAlphaAndRotationObjectAnimator(view: View, isLoop: Boolean = false): AnimatorSet {
        val objectAnimator = ObjectAnimator.ofFloat(view, "alpha", 0f, 0.5f, 1f).apply {
            duration = 500
            interpolator = LinearInterpolator()
            if (isLoop) {
                repeatMode = ValueAnimator.RESTART
                repeatCount = ValueAnimator.INFINITE
            }
        }
        val objectAnimator2 = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f).apply {
            duration = 1000
            interpolator = LinearInterpolator()
            if (isLoop) {
                repeatMode = ValueAnimator.RESTART
                repeatCount = ValueAnimator.INFINITE
            }
        }
        val animatorSet = AnimatorSet().apply {
            play(objectAnimator).with(objectAnimator2)
            //取消动画，状态恢复原来状态
            doOnCancel {
                view.alpha = 1f
                view.rotation = 0f
            }
            start()
        }
        return animatorSet
    }

    /**
     * 围绕自身中心旋转360度
     */
    fun viewRotationAnimator(view: View, isLoop: Boolean = false): AnimatorSet {
        val rotationAnimator = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f).apply {
            duration = 1000
            interpolator = LinearInterpolator()
            if (isLoop) {
                repeatMode = ValueAnimator.RESTART
                repeatCount = ValueAnimator.INFINITE
            }
        }
        val animatorSet = AnimatorSet().apply {
            play(rotationAnimator)
            //取消动画，状态恢复原来状态
            doOnCancel {
                view.rotation = 0f
            }
            start()
        }
        return animatorSet
    }


    /**
     * 加载动画文件执行动画
     */
    fun viewLoadAnimation(
        context: Context,
        view: View,
        animId: Int = R.anim.scale_enter,
        durationMillis: Long = 2000,
        startOffset: Long = 3000
    ): Animation {
        val animation = AnimationUtils.loadAnimation(context, animId)
        animation.duration = durationMillis
        animation.startOffset = startOffset
        view.startAnimation(animation)
        return animation
    }

    /**
     * 控件淡入显示
     */
    fun viewShowFadeInAnimation(target: View, duration: Long = 350): YoYoString {
        return YoYo.with(Techniques.FadeIn).duration(duration).onStart {
            if (target.isGone || target.isInvisible) {
                target.post {
                    target.visibility = View.VISIBLE
                }
            }
        }.playOn(target)
    }

    /**
     * 控件淡出隐藏
     */
    fun viewHideFadeInAnimation(target: View, duration: Long = 350, hideType: Int = View.GONE) {
        YoYo.with(Techniques.FadeOut).duration(duration).onEnd {
            if (target.isVisible) target.visibility = hideType
        }.playOn(target)
    }

    /**
     * 添加菜单数据
     */
    fun addMenuBean(
        list: MutableList<MenuTxtBean>,
        name: String,
        value: String = "",
        imageResId: Int = 0,
        imageUrl: String = "",
        colorRedId: Int = R.color.orange_color3,
        isSwitch: Boolean = false,
        type: Int = ConstantInt.Type0,
        state: Int = ConstantInt.Type0,
        @MultipleEntity menuType: Int = MultipleEntity.TEXT
    ) {
        val menuTxtBean = MenuTxtBean(name, value, menuType)
        if (imageResId > 0) {
            menuTxtBean.imageId = imageResId
        }
        if (state > 0) {
            menuTxtBean.state = state
        }
        if (!TextUtils.isEmpty(imageUrl)) {
            menuTxtBean.imageUrl = imageUrl
        }
        if (isSwitch) {
            menuTxtBean.isSwitch = true
        }
        menuTxtBean.colorRedId = colorRedId
        menuTxtBean.type = type
        list.add(menuTxtBean)
    }

    /**
     * 更新选中的状态item
     */
    fun updateDataBeanOnlySelectedItem(
        adapter: BaseRecyclerAdapter<*>, list: MutableList<DataBean>, position: Int
    ) {
        if (position > list.size - 1 || position < 0) return
        val dataBean = list[position]
        if (dataBean.selected) return
        for (i in 0 until list.size) {
            val data = list[i]
            if (data.selected) {
                data.selected = false
                adapter.notifyItemChanged(i)
                break
            }
        }
        dataBean.selected = true
        adapter.notifyItemChanged(position)
    }

    /**
     * 显示地图类型选择弹窗
     */
    fun getMapTypeDialog(
        context: Context,
        onItemClickListener: BaseRecyclerAdapter.OnItemClickListener? = null,
        fenceCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null,
        dashedCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null
    ): SelectMapTypeDialog {
        val mapType = Util.getMapTypeSp()
        val typeList = mutableListOf<DataBean>()
        DataBean().apply {
            selected = mapType == ConstantInt.Type0
            imageId = R.drawable.icon_map_standard_type
            name = context.getString(R.string.txt_standard)
            typeList.add(this)
        }
        DataBean().apply {
            selected = mapType == ConstantInt.Type1
            imageId = R.drawable.icon_map_satellite_type
            name = context.getString(R.string.txt_satellite)
            typeList.add(this)
        }
        val mapTypeAdapter = SelectMapTypeCardShadeAdapter(context, typeList).apply {
            setOnItemClickListener(object : BaseRecyclerAdapter.OnItemClickListener {
                override fun onItemClick(itemView: View?, pos: Int) {
                    updateDataBeanOnlySelectedItem(this@apply, typeList, pos)
                    onItemClickListener?.onItemClick(itemView, pos)
                }
            })
        }
        return SelectMapTypeDialog(
            context, mapTypeAdapter, fenceCheckedChangeListener, dashedCheckedChangeListener
        )
    }

    /**
     * 设置切换位置按钮图片
     */
    fun setMapSwitchLocationButtonImage(iv: ImageView, locationType: Int) {
        viewShowFadeInAnimation(iv, 600)
        when (locationType) {
            ConstantInt.PetSpecialType -> {
                iv.setBackgroundResource(R.drawable.shape_white_circle_bg)
                iv.setImageResource(R.drawable.icon_pet_foot_svg)
                iv.setPadding(AppUtils.dpToPx(14))
            }

            ConstantInt.PetLocationType -> {
                iv.setBackgroundResource(R.drawable.shape_yellow_circle_bg)
                iv.setImageResource(R.drawable.icon_pet_foot_svg)
                iv.setPadding(AppUtils.dpToPx(14))
            }

            ConstantInt.UserLocationType -> {
                iv.setBackgroundResource(R.drawable.shape_white_circle_bg)
                iv.setImageResource(R.drawable.icon_user_head_svg)
                iv.setPadding(AppUtils.dpToPx(13))
            }

            ConstantInt.OtherLocationType -> {
                iv.setBackgroundResource(R.drawable.shape_white_circle_bg)
                iv.setImageResource(R.drawable.icon_pet_fence_svg)
                iv.setPadding(AppUtils.dpToPx(13))
            }

            ConstantInt.DefaultType -> {
                iv.setBackgroundResource(R.drawable.shape_white_circle_bg)
                iv.setImageResource(R.drawable.icon_map_gps)
                iv.setPadding(AppUtils.dpToPx(13))
            }
        }
    }


    /**
     * 跳转隐私政策
     */
    fun goPrivacyPolicy(activity: Activity) {
        val url = if (AppUtils.isChina()) {
            "file:///android_asset/privacy_cn.html"
        } else {
            "file:///android_asset/privacy_en.html"
        }
        WebViewActivity.startWebViewActivity(
            activity, activity.getString(R.string.txt_privacy_policy), url
        )
    }

    /**
     * 跳转服务协议
     */
    fun goServiceContract(activity: Activity) {
        val url = if (AppUtils.isChina()) {
            "file:///android_asset/terms_cn.html"
        } else {
            "file:///android_asset/terms_en.html"
        }
        WebViewActivity.startWebViewActivity(
            activity, activity.getString(R.string.txt_service_contract), url
        )
    }

    /**
     * 设置显示隐藏密码
     */
    fun setShowAndHidePassword(
        editText: EditText, hideShowImBtn: QMUIAlphaImageButton
    ) {
        editText.apply {
            val filter = arrayOf<InputFilter>(InputFilter.LengthFilter(60))
            filters = filter
            transformationMethod = PasswordTransformationMethod.getInstance()
            inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD
        }
        hideShowImBtn.apply {
            visibility = View.VISIBLE
            setImageResource(R.drawable.icon_hide_password_svg)
            setChangeAlphaWhenPress(true)
        }
    }

    /**
     * 显示隐藏密码事件
     */
    fun showAndHidePasswordClick(
        editText: EditText, hideShowImBtn: QMUIAlphaImageButton, isShowPassword: Boolean
    ) {
        val imageResId = if (isShowPassword) {
            editText.transformationMethod = HideReturnsTransformationMethod.getInstance()
            R.drawable.icon_show_password_svg
        } else {
            editText.transformationMethod = PasswordTransformationMethod.getInstance()
            R.drawable.icon_hide_password_svg
        }
        hideShowImBtn.setImageResource(imageResId)
        editText.setSelection(editText.text.toString().length)
    }

    /**
     * 设置EditText不可编辑，下拉状态
     */
    fun setEditTextDropSelectState(editText: EditText, hintResId: Int = R.string.txt_select) {
        editText.apply {
            isEnabled = false
            layoutParams.width = RelativeLayout.LayoutParams.WRAP_CONTENT
            setHint(hintResId)
        }
    }

    /**
     * 设置已选择宠物显示
     */
    fun selectPetDialogShow(
        context: Context,
        petList: MutableList<PetBean>,
        selectPos: Int,
        petName: TextView,
        petHead: ImageView
    ) {
        if (petList.size == 0) {
            petName.text = context.getString(R.string.no_pet)
            petHead.load(R.drawable.icon_pet_default_head_svg)
            return
        }
        val pet = petList[selectPos]
        savePetSP(pet, selectPos)
        petName.text = pet.petName
        setPetTypeHead(petHead, pet.imgurl, pet.petType)
        viewAlphaAndRotationObjectAnimator(petHead)
    }

    /**
     * 保存宠物相关数据到本地
     */
    private fun savePetSP(petBean: PetBean, selectPos: Int) {
        //保存已选宠物下标
        MMKVUtil.putInt(MMKVKey.PetSelectPosition, selectPos)
        //保存当前设备的套餐类型，控制权限
        MMKVUtil.putInt(MMKVKey.MealType, petBean.mealType)
        //套餐是否过期
        MMKVUtil.putInt(MMKVKey.AvailableOrder, petBean.availableOrder)
        LogUtil.e("保存宠物相关数据到本地,savePetSP")
        //保存当前宠物是否分享的
        MMKVUtil.putInt(MMKVKey.Shared, petBean.shared)
    }

    /**
     * ViewPager2配置信息
     */
    fun setViewPager2Config(
        viewPager2: ViewPager2,
        callback: ViewPager2.OnPageChangeCallback?,
        pageLimit: Int = 0,
        isCanSlide: Boolean = false
    ) {
        viewPager2.apply {
            //禁止ViewPager滑动
            isUserInputEnabled = isCanSlide
            if (pageLimit > 0) offscreenPageLimit = pageLimit
            //滑动动画
//            it.setPageTransformer(CompositePageTransformer())
//            (getChildAt(0) as RecyclerView).layoutManager!!.isItemPrefetchEnabled = false
            (getChildAt(0) as RecyclerView).let {
                it.layoutManager?.isItemPrefetchEnabled = false
                //滑动动画
//                itemAnimator = DefaultItemAnimator()
            }
            callback?.let {
                registerOnPageChangeCallback(it)
            }
        }
    }

    /**
     * 获取围栏的类型图片
     */
    fun getFenceNameImageType(fenceNameType: Int): Int {
        var fenceNameTypeImage = 0
        when (fenceNameType) {
            1 -> fenceNameTypeImage = R.drawable.icon_save_zone_type1_svg
            2 -> fenceNameTypeImage = R.drawable.icon_save_zone_type2_svg
            3 -> fenceNameTypeImage = R.drawable.icon_save_zone_type3_svg
            4 -> fenceNameTypeImage = R.drawable.icon_save_zone_type4_svg
            5 -> fenceNameTypeImage = R.drawable.icon_save_zone_type5_svg
            6 -> fenceNameTypeImage = R.drawable.icon_no_zone_type1_svg
            7 -> fenceNameTypeImage = R.drawable.icon_no_zone_type2_svg
            8 -> fenceNameTypeImage = R.drawable.icon_no_zone_type3_svg
        }
        return fenceNameTypeImage
    }

    /**
     * 设置宠物头像
     */
    fun setPetTypeHead(imageView: ImageView, imageUrl: String, type: Int) {
        if (TextUtils.isEmpty(imageUrl)) {
            val defaultHead = if (type == 2) R.drawable.icon_pet_default_head_svg
            else R.drawable.icon_pet_default_head_svg
            imageView.load(defaultHead)
        } else {
            imageLoadUrl(imageView, imageUrl)
        }
    }

    /**
     * 操作提示框
     */
    fun operateDialogTips(context: Context, messageID: Int, okCallback: () -> Unit) {
        showDialog(context, messageID, object : BaseDialog.OnDialogOkListener {
            override fun onOkClick(dialog: BaseDialog<*>) {
                dialog.dismiss()
                okCallback()
            }
        }, okTextResId = R.string.start_txt_yes)
    }

    /**
     * 手动连接蓝牙提示
     */
    fun bleConActionState(
        baseActivity: BaseActivity<*>,
        textView: TextView,
        conState: Int,
        gravity: Int = Gravity.BOTTOM
    ) {
        when (conState) {
            ConState.CONNECTING, ConState.CONNECTING_MAC -> {
                textView.text = baseActivity.getString(R.string.txt_connecting)
            }

            else -> {
                textView.text = baseActivity.getString(R.string.tracker_manage_set_ble_unconnect)
//                baseActivity.showToast(R.string.txt_ble_connect_fail, gravity = gravity)
            }
        }
        textView.setBackgroundColor(ContextCompat.getColor(baseActivity, R.color.red_color4))
    }

    fun bleConStateToast(
        baseActivity: BaseActivity<*>, conState: Int, gravity: Int = Gravity.BOTTOM
    ) {
        when (conState) {
            ConState.CONNECTED -> baseActivity.showToast(
                R.string.txt_connect_success, gravity = gravity
            )

            ConState.DISCONNECTED -> baseActivity.showToast(
                R.string.txt_unconnect_no, gravity = gravity
            )

//            else -> baseActivity.showToast(R.string.txt_connect_fail, gravity = gravity)
        }
    }

    /**
     * 手动连接/断开设备
     */
    fun connectionBtn(
        context: Context, btnString: String, mac: String, noConnectCallback: () -> Unit
    ) {
        if (btnString == context.getString(R.string.tracker_manage_set_ble_unconnect)) {
            noConnectCallback()
        } else if (btnString == context.getString(R.string.tracker_manage_set_ble_connect)) {
//            operateDialogTips(context, R.string.txt_disconnect_tips) {
//                SRBleUtil.instance.disconnectToMac(mac)
//            }
        }
    }

    fun viewShow(view: View) {
        if (view.isGone || view.isInvisible) view.visibility = View.VISIBLE
    }
}