package com.adealink.frame.imkit.widget.adapter

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.Spannable
import android.text.util.Linkify
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnLongClickListener
import android.view.View.OnTouchListener
import android.view.ViewGroup
import android.widget.Checkable
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.RatingBar
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

open class ViewHolder(val context: Context, val convertView: View) : RecyclerView.ViewHolder(
    convertView
) {
    private val views = SparseArray<View?>()
    private var viewHolderScope = CoroutineScope(
        SupervisorJob() + Dispatcher.UI
    )

    /**
     * 通过viewId获取控件
     *
     * @param viewId
     * @return
     */
    fun <T : View?> getView(viewId: Int): T? {
        var view = views[viewId]
        if (view == null) {
            view = convertView.findViewById(viewId)
            views.put(viewId, view)
        }
        return view as? T?
    }

    fun launch(
        context: CoroutineContext = EmptyCoroutineContext,
        block: suspend CoroutineScope.() -> Unit
    ){
        if (!viewHolderScope.isActive) {
            viewHolderScope = CoroutineScope(
                SupervisorJob() + Dispatcher.UI
            )
        }
        viewHolderScope.launch(context, block = block)
    }

    fun cancelJob() {
        viewHolderScope.cancel()
    }

    fun clear() {
        cancelJob()
    }

    // 以下为辅助方法
    /**
     * 设置TextView的值
     *
     * @param viewId
     * @param text
     * @return
     */
    fun setText(viewId: Int, text: String?): ViewHolder {
        val tv = getView<TextView>(viewId)
            ?: return this
        tv.text = text
        return this
    }

    fun setText(viewId: Int, text: Spannable?): ViewHolder {
        val tv = getView<TextView>(viewId)
            ?: return this
        tv.text = text
        return this
    }

    fun setText(viewId: Int, text: CharSequence?, type: TextView.BufferType?): ViewHolder {
        val tv = getView<TextView>(viewId)
            ?: return this
        tv.setText(text, type)
        return this
    }

    fun setImageResource(viewId: Int, resId: Int): ViewHolder {
        val view = getView<ImageView>(viewId)
            ?: return this
        try {
            view.setImageResource(resId)
        } catch (e: Exception) {

        }
        return this
    }

    fun setImageBitmap(viewId: Int, bitmap: Bitmap?): ViewHolder {
        val view = getView<ImageView>(viewId)
            ?: return this
        view.setImageBitmap(bitmap)
        return this
    }

    fun setImageDrawable(viewId: Int, drawable: Drawable?): ViewHolder {
        val view = getView<ImageView>(viewId)
            ?: return this
        view.setImageDrawable(drawable)
        return this
    }

    fun setBackgroundColor(viewId: Int, color: Int): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.setBackgroundColor(color)
        return this
    }

    fun setBackgroundRes(viewId: Int, backgroundRes: Int): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.setBackgroundResource(backgroundRes)
        return this
    }

    fun setBackgroundDrawable(viewId: Int, drawable: Drawable?): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.background = drawable
        return this
    }

    fun setTextColor(viewId: Int, textColor: Int): ViewHolder {
        val view = getView<TextView>(viewId)
            ?: return this
        view.setTextColor(textColor)
        return this
    }

    fun setTextColorRes(viewId: Int, textColorRes: Int): ViewHolder {
        val view = getView<TextView>(viewId)
            ?: return this
        view.setTextColor(context.resources.getColor(textColorRes))
        return this
    }

    fun setVisible(viewId: Int, visible: Boolean): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.visibility = if (visible) View.VISIBLE else View.GONE
        return this
    }

    fun setHoldVisible(viewId: Int, visible: Boolean): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.visibility = if (visible) View.VISIBLE else View.INVISIBLE
        return this
    }

    fun linkify(viewId: Int): ViewHolder {
        val view = getView<TextView>(viewId)
            ?: return this
        Linkify.addLinks(view, Linkify.ALL)
        return this
    }

    fun setTypeface(typeface: Typeface?, vararg viewIds: Int): ViewHolder {
        for (viewId in viewIds) {
            val view = getView<TextView>(viewId) ?: continue
            view.typeface = typeface
            view.paintFlags = view.paintFlags or Paint.SUBPIXEL_TEXT_FLAG
        }
        return this
    }

    fun setProgress(viewId: Int, progress: Int): ViewHolder {
        val view = getView<ProgressBar>(viewId)
            ?: return this
        view.progress = progress
        return this
    }

    fun setProgress(viewId: Int, progress: Int, max: Int): ViewHolder {
        val view = getView<ProgressBar>(viewId)
            ?: return this
        view.max = max
        view.progress = progress
        return this
    }

    fun setMax(viewId: Int, max: Int): ViewHolder {
        val view = getView<ProgressBar>(viewId)
            ?: return this
        view.max = max
        return this
    }

    fun setRating(viewId: Int, rating: Float): ViewHolder {
        val view = getView<RatingBar>(viewId)
            ?: return this
        view.rating = rating
        return this
    }

    fun setRating(viewId: Int, rating: Float, max: Int): ViewHolder {
        val view = getView<RatingBar>(viewId)
            ?: return this
        view.max = max
        view.rating = rating
        return this
    }

    fun setTag(viewId: Int, tag: Any?): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.tag = tag
        return this
    }

    fun setTag(viewId: Int, key: Int, tag: Any?): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.setTag(key, tag)
        return this
    }

    fun setChecked(viewId: Int, checked: Boolean): ViewHolder {
        val view = getView<View>(viewId) as Checkable?
            ?: return this
        view.isChecked = checked
        return this
    }

    fun setSelected(viewId: Int, selected: Boolean): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.isSelected = selected
        return this
    }

    /** 关于事件的  */
    fun setOnClickListener(viewId: Int, listener: View.OnClickListener?): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.setOnClickListener(listener)
        return this
    }

    fun setOnTouchListener(viewId: Int, listener: OnTouchListener?): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.setOnTouchListener(listener)
        return this
    }

    fun setOnLongClickListener(viewId: Int, listener: OnLongClickListener?): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.setOnLongClickListener(listener)
        return this
    }

    fun setPadding(viewId: Int, left: Int, top: Int, right: Int, bottom: Int): ViewHolder {
        val view = getView<View>(viewId)
            ?: return this
        view.setPadding(left, top, right, bottom)
        return this
    }

    companion object {
        fun createViewHolder(context: Context, itemView: View): ViewHolder {
            val holder = ViewHolder(context, itemView)
            return holder
        }

        fun createViewHolder(context: Context, parent: ViewGroup?, layoutId: Int): ViewHolder {
            val itemView = LayoutInflater.from(context).inflate(layoutId, parent, false)
            return createViewHolder(context, itemView)
        }
    }
}
