package com.ym.admodule.ks

import android.annotation.SuppressLint
import android.app.Activity
import android.os.Handler
import android.os.Message
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.Glide
import com.kwad.sdk.api.*
import com.kwad.sdk.api.KsLoadManager.SplashScreenAdListener
import com.kwad.sdk.api.KsNativeAd.VideoPlayListener
import com.kwad.sdk.api.KsSplashScreenAd.SplashScreenAdInteractionListener
import com.ym.admodule.R
import com.ym.admodule.config.AdInfo
import com.ym.admodule.config.ZXADCallback
import com.ym.admodule.gdt.GDTAdUtils
import com.ym.admodule.listener.ZXADSplashListener
import com.ym.admodule.listener.ZXADVideoListener
import com.ym.modulecommon.AppliContext
import com.ym.modulecommon.base.BaseActivity
import com.ym.modulecommon.module.NewsEntity
import com.ym.modulecommon.utils.AdEventUtils
import com.ym.modulecommon.utils.AdEventUtils.onEventClick
import com.ym.modulecommon.utils.AdEventUtils.onEventPullFail
import com.ym.modulecommon.utils.AdEventUtils.onEventPullSuccess
import com.ym.modulecommon.utils.AdEventUtils.onEventShow
import com.ym.modulecommon.utils.AdEventUtils.onEventShowFail
import com.ym.modulecommon.utils.LogUtils
import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue

/**
 * Craeted by ${junqi.li}
 * Craeted by 2020/10/19
 */
class KSADUtils {

    private class AdSingleImageViewHolder internal constructor(convertView: View) :
        AdBaseViewHolder(convertView) {
        var mAdImage: ImageView = convertView.findViewById(R.id.ad_image)
    }

    private open class AdBaseViewHolder internal constructor(convertView: View) {
        var mAdDes: TextView
        var mAppContainer: ViewGroup
        var mAppIcon: ImageView
        var mAppName: TextView
        var mAppDesc: TextView
        var mAppDownloadBtn: TextView
        var mH5Container: ViewGroup
        var mH5Desc: TextView
        var mH5OpenBtn: TextView
        var mDislikeBtn: ImageView

        init {
            mAdDes = convertView.findViewById(R.id.ad_desc)
            mAppContainer =
                convertView.findViewById(R.id.ad_download_container)
            mAppIcon =
                convertView.findViewById(R.id.app_icon)
            mAppName =
                convertView.findViewById(R.id.app_title)
            mAppDesc =
                convertView.findViewById(R.id.app_desc)
            mAppDownloadBtn =
                convertView.findViewById(R.id.app_download_btn)
            mH5Container =
                convertView.findViewById(R.id.ad_h5_container)
            mH5Desc =
                convertView.findViewById(R.id.h5_desc)
            mH5OpenBtn =
                convertView.findViewById(R.id.h5_open_btn)
            mDislikeBtn =
                convertView.findViewById(R.id.ad_dislike)
        }
    }

    private class AdVideoViewHolder internal constructor(convertView: View) :
        AdBaseViewHolder(convertView) {
        var mAdVideoContainer: FrameLayout = convertView.findViewById(R.id.video_container)

    }

    private class AdGroupImageViewHolder internal constructor(convertView: View) :
        AdBaseViewHolder(convertView) {
        var mAdImageLeft: ImageView
        var mAdImageMid: ImageView
        var mAdImageRight: ImageView

        init {
            mAdImageLeft =
                convertView.findViewById(R.id.ad_image_left)
            mAdImageMid =
                convertView.findViewById(R.id.ad_image_mid)
            mAdImageRight =
                convertView.findViewById(R.id.ad_image_right)
        }
    }

    private class NormalViewHolder internal constructor(convertView: View) {
        var textView: TextView = convertView.findViewById(R.id.tv)

    }

    companion object {
        private const val TAG = "KSADUtils"
        private var mRewardVideoAd: KsRewardVideoAd? = null
        private var mNativeAdContainer: FrameLayout? = null
        private var entity: NewsEntity? = null
        private var mActivity: Activity? = null

        //原生 信息流
        fun loadFeedNativeAd(
            activity: Activity?,
            newsEntity: NewsEntity,
            container: FrameLayout,
            zxadCallback: ZXADCallback
        ) {
            mNativeAdContainer = container
            entity = newsEntity
            mActivity = activity
            val scene = KsScene.Builder(newsEntity.codeId.toLong()).adNum(1)
                .build()
            scene.adNum = 1
            KsAdSDK.getLoadManager().loadNativeAd(scene, object : KsLoadManager.NativeAdListener {
                override fun onError(code: Int, msg: String) {
                    onEventPullFail(newsEntity, AdEventUtils.AD_MODEL_BIGIMG)
                    AdEventUtils.onEvent(newsEntity,code,msg)
                    container.visibility = View.GONE
                    zxadCallback.onAdFail()
                }

                override fun onNativeAdLoad(adList: List<KsNativeAd>?) {
                    if (adList == null || adList.isEmpty()) {
                        return
                    }
                    onEventPullSuccess(newsEntity, AdEventUtils.AD_MODEL_BIGIMG)
                    zxadCallback.onAdSuccess()
                    showAd(adList[0])
                }
            })
        }

        fun loadFeedNativeAd(
            newsEntity: NewsEntity,
            zxadCallback: ZXADCallback
        ) {
            val scene = KsScene.Builder(newsEntity.codeId.toLong()).adNum(1)
                .build()
            scene.adNum = 1
            KsAdSDK.getLoadManager().loadNativeAd(scene, object : KsLoadManager.NativeAdListener {
                override fun onError(code: Int, msg: String) {
                    onEventPullFail(newsEntity, AdEventUtils.AD_MODEL_BIGIMG)
                    AdEventUtils.onEvent(newsEntity,code,msg)
                    zxadCallback.onAdFail()
                }

                override fun onNativeAdLoad(adList: List<KsNativeAd>?) {
                    if (adList == null || adList.isEmpty()) {
                        return
                    }
                    onEventPullSuccess(newsEntity, AdEventUtils.AD_MODEL_BIGIMG)
                    zxadCallback.onAdSuccess()
                    mKsFeedAdCacheMap?.add(adList[0])
                }
            })
        }

        fun showFeedAd(
            activity: Activity?, newsEntity: NewsEntity?,
            container: FrameLayout?
        ) {
            LogUtils.d(TAG, "run 快手 信息流 showFeedAd")
            if (mKsFeedAdCacheMap != null && !mKsFeedAdCacheMap.isEmpty() && mKsFeedAdCacheMap[mKsFeedAdCacheMap.size - 1] != null
            ) {
                mNativeAdContainer = container
                entity = newsEntity
                mActivity = activity
                showAd(mKsFeedAdCacheMap[mKsFeedAdCacheMap.size - 1])
            }
        }

        fun loadSplashAd(
            newsEntity: NewsEntity,
            activity: Activity,
            container: ViewGroup,
            zxadListener: ZXADSplashListener,
            zxadCallback: ZXADCallback
        ) {
            val scene = KsScene.Builder(newsEntity.codeId.toLong())
                .build()
            KsAdSDK.getLoadManager().loadSplashScreenAd(scene, object : SplashScreenAdListener {
                override fun onError(code: Int, msg: String) {
                    onEventPullFail(newsEntity, AdEventUtils.AD_MODEL_SPLAH)
                    AdEventUtils.onEvent(newsEntity,code,msg)
                    container.visibility = View.GONE
                    zxadCallback.onAdFail()
                }

                override fun onSplashScreenAdLoad(splashScreenAd: KsSplashScreenAd?) {
                    onEventPullSuccess(newsEntity, AdEventUtils.AD_MODEL_SPLAH)
                    zxadCallback.onAdSuccess()
                    container.visibility = View.VISIBLE
                    val fragment =
                        splashScreenAd?.getFragment(object : SplashScreenAdInteractionListener {
                            override fun onAdClicked() {
                                onEventClick(newsEntity, AdEventUtils.AD_MODEL_BIGIMG)
                            }

                            override fun onAdShowError(
                                code: Int,
                                extra: String
                            ) {
                                onEventShowFail(newsEntity, AdEventUtils.AD_MODEL_BIGIMG)
                                zxadCallback.onAdFail()
                            }

                            override fun onAdShowEnd() {
                                zxadListener.onAdSkip()
                            }

                            override fun onAdShowStart() {
                                zxadListener.onAdShow()
                                onEventShow(newsEntity)
                            }

                            override fun onSkippedAd() {
                                zxadListener.onAdSkip()
                            }
                        })
                    if (!activity.isFinishing) {
                        (activity as BaseActivity).supportFragmentManager.beginTransaction()
                            .replace(container.id, fragment!!)
                            .commitAllowingStateLoss()
                    }
                }
            })
        }

        fun loadRewardVideoAd(
            activity: Activity?,
            entity: NewsEntity,
            listener: ZXADVideoListener,
            callback: ZXADCallback
        ) {
            val scene =
                KsScene.Builder(entity.codeId.toLong()).build()
            KsAdSDK.getLoadManager()
                .loadRewardVideoAd(scene, object : KsLoadManager.RewardVideoAdListener {
                    override fun onError(code: Int, msg: String) {
                        onEventPullFail(entity, AdEventUtils.AD_MODEL_REWARD)
                        AdEventUtils.onEvent(entity,code,msg)
                        callback.onAdFail()
                    }

                    override fun onRewardVideoAdLoad(adList: List<KsRewardVideoAd>?) {
                        if (adList != null && adList.size > 0) {
                            onEventPullSuccess(entity, AdEventUtils.AD_MODEL_REWARD)
                            mRewardVideoAd = adList[0]
                            callback.onAdSuccess()
                            listener.onSuccess()
                        } else {
                            callback.onAdFail()
                        }
                    }
                })
            val startTime = System.currentTimeMillis()
            val handler: Handler = object : Handler() {
                override fun handleMessage(msg: Message) {
                    super.handleMessage(msg)
                    if (System.currentTimeMillis() - startTime > 7000) {
                        if (entity != null) {
                            onEventPullFail(entity, AdEventUtils.AD_MODEL_REWARD)
                        }
                        callback.onAdFail()
                        removeCallbacksAndMessages(null)
                        return
                    }
                    if (mRewardVideoAd != null && mRewardVideoAd!!.isAdEnable) {
                        mRewardVideoAd!!
                            .setRewardAdInteractionListener(object :
                                KsRewardVideoAd.RewardAdInteractionListener {
                                override fun onAdClicked() {
                                    listener.onAdVideoBarClick()
                                    if (entity != null) {
                                        onEventClick(entity, AdEventUtils.AD_MODEL_REWARD)
                                    }
                                }

                                override fun onPageDismiss() {
                                    listener.onAdClose(AdInfo(entity.codeId))
                                }

                                override fun onVideoPlayError(
                                    code: Int,
                                    extra: Int
                                ) {
                                    onEventShowFail(entity, AdEventUtils.AD_MODEL_REWARD)
                                    callback.onAdFail()
                                }

                                override fun onVideoPlayEnd() {
                                }

                                override fun onVideoPlayStart() {
                                    listener.onAdShow()
                                    onEventShow(entity)
                                }

                                override fun onRewardVerify() {
                                    AdEventUtils.onEventComplete(
                                        entity,
                                        AdEventUtils.AD_MODEL_REWARD
                                    )
                                }
                            })
                        mRewardVideoAd!!.showRewardVideoAd(activity, null)
                        removeCallbacksAndMessages(null)
                    } else {
                        sendEmptyMessageDelayed(1, 20)
                    }
                }
            }
            handler.sendEmptyMessageDelayed(1, 20)
        }

        /**
         * 加载自渲染View
         */
        private fun showAd(ksNativeAd: KsNativeAd?) {
            mNativeAdContainer!!.removeAllViews()
            var adView: View? = null
            adView = when (ksNativeAd!!.materialType) {
                KsNativeAd.MaterialType.VIDEO ->                 // 视频素材，渲染自定义的视频广告
                    getVideoItemView(
                        mNativeAdContainer,
                        ksNativeAd
                    )
                KsNativeAd.MaterialType.SINGLE_IMG ->                 // 单图素材，渲染自定义的单图广告
                    getSingleImageItemView(
                        mNativeAdContainer,
                        ksNativeAd
                    )
                KsNativeAd.MaterialType.GROUP_IMG ->                 // 组图素材，渲染自定义的组图广告
                    getGroupImageItemView(
                        mNativeAdContainer,
                        ksNativeAd
                    )
                KsNativeAd.MaterialType.UNKNOWN -> getNormalItemView(mNativeAdContainer)
                else -> getNormalItemView(mNativeAdContainer)
            }
            if (adView != null && adView.parent == null) {
                mNativeAdContainer!!.visibility = View.VISIBLE
                mNativeAdContainer!!.addView(adView)
                LogUtils.d(TAG, "run 快手 信息流 显示")
            }
        }

        /**
         * 使用SDK渲染的播放控件
         */
        protected fun getVideoItemView(
            parent: ViewGroup?,
            ksNativeAd: KsNativeAd?
        ): View {
            val convertView =
                LayoutInflater.from(parent!!.context)
                    .inflate(R.layout.native_item_video, parent, false)
            val videoViewHolder = AdVideoViewHolder(convertView)

            // 设置广告数据
            bindCommonData(
                convertView as ViewGroup,
                videoViewHolder,
                ksNativeAd
            )
            ksNativeAd!!.setVideoPlayListener(object : VideoPlayListener {
                override fun onVideoPlayStart() {}
                override fun onVideoPlayComplete() {}
                override fun onVideoPlayError(
                    what: Int,
                    extra: Int
                ) {
                }
            })

            // SDK默认渲染的视频view
            val videoPlayConfig = KsAdVideoPlayConfig.Builder()
                .videoSoundEnable(true) // 有声播放
                .dataFlowAutoStart(true) // 流量下自动播放
                .build()
            val videoView =
                ksNativeAd.getVideoView(parent.context, videoPlayConfig)
            if (videoView != null && videoView.parent == null) {
                videoViewHolder.mAdVideoContainer.removeAllViews()
                videoViewHolder.mAdVideoContainer.addView(videoView)
            }
            return convertView
        }

        @SuppressLint("DefaultLocale")
        protected fun getNormalItemView(parent: ViewGroup?): View {
            val convertView =
                LayoutInflater.from(parent!!.context)
                    .inflate(R.layout.native_item_normal, parent, false)
            val normalViewHolder =
                NormalViewHolder(convertView)
            normalViewHolder.textView.text = "没有广告"
            return convertView
        }

        protected fun getGroupImageItemView(
            parent: ViewGroup?,
            ksNativeAd: KsNativeAd?
        ): View {
            val convertView =
                LayoutInflater.from(parent!!.context)
                    .inflate(R.layout.native_item_group_image, parent, false)
            val viewHolder = AdGroupImageViewHolder(convertView)
            bindCommonData(
                convertView as ViewGroup,
                viewHolder,
                ksNativeAd
            )

            // 获取图片资源
            val ksImageList = ksNativeAd!!.imageList
            if (ksImageList != null && !ksImageList.isEmpty()) {
                for (i in ksImageList.indices) {
                    val image = ksNativeAd.imageList!![i]
                    if (image != null && image.isValid) {
                        if (i == 0) {
                            Glide.with(parent.context).load(image.imageUrl)
                                .into(viewHolder.mAdImageLeft)
                        } else if (i == 1) {
                            Glide.with(parent.context).load(image.imageUrl)
                                .into(viewHolder.mAdImageMid)
                        } else if (i == 2) {
                            Glide.with(parent.context).load(image.imageUrl)
                                .into(viewHolder.mAdImageRight)
                        }
                    }
                }
            }
            return convertView
        }

        protected fun getSingleImageItemView(
            parent: ViewGroup?,
            ksNativeAd: KsNativeAd?
        ): View {
            val convertView =
                LayoutInflater.from(parent!!.context)
                    .inflate(R.layout.native_item_single_image, parent, false)
            val viewHolder = AdSingleImageViewHolder(convertView)
            bindCommonData(
                convertView as ViewGroup,
                viewHolder,
                ksNativeAd
            )

            // 获取图片资源
            if (ksNativeAd!!.imageList != null && !ksNativeAd.imageList!!.isEmpty()) {
                val image = ksNativeAd.imageList!![0]
                if (image != null && image.isValid) {
                    Glide.with(parent.context).load(image.imageUrl)
                        .into(viewHolder.mAdImage)
                }
            }
            return convertView
        }

        private fun bindCommonData(
            convertView: ViewGroup, adBaseViewHolder: AdBaseViewHolder,
            ad: KsNativeAd?
        ) {
            val clickViewList: MutableList<View> =
                ArrayList()
            clickViewList.add(convertView) // 点击整个view都可触发转换
            clickViewList.add(adBaseViewHolder.mAppDownloadBtn)
            clickViewList.add(adBaseViewHolder.mH5OpenBtn)

            // 注册View的点击，点击后触发转化
            ad!!.registerViewForInteraction(convertView, clickViewList,
                object : KsNativeAd.AdInteractionListener {
                    override fun onAdClicked(
                        view: View,
                        ad: KsNativeAd
                    ) {
                        onEventClick(entity!!, AdEventUtils.AD_MODEL_BIGIMG)
                    }

                    override fun onAdShow(ad: KsNativeAd) {
                        onEventShow(entity!!)
                    }
                })
            // 广告描述
            adBaseViewHolder.mAdDes.text = ad.adDescription
            ad.appScore
            ad.appDownloadCountDes
            when (ad.interactionType) {
                KsNativeAd.InteractionType.H5 -> {
                    // 广告描述
                    adBaseViewHolder.mH5Desc.text = ad.adDescription
                    // 广告转化文案
                    adBaseViewHolder.mH5OpenBtn.text = ad.actionDescription
                    adBaseViewHolder.mAppContainer.visibility = View.GONE
                    adBaseViewHolder.mH5Container.visibility = View.VISIBLE
                }
                KsNativeAd.InteractionType.DOWNLOAD -> {
                    // appIcon，非下载类型的没有
                    if (TextUtils.isEmpty(ad.appIconUrl)) {
                        adBaseViewHolder.mAppIcon.visibility = View.GONE
                    } else {
                        adBaseViewHolder.mAppIcon.visibility = View.VISIBLE

                        Glide.with(AppliContext.get()).load(ad.appIconUrl)
                            .into(adBaseViewHolder.mAppIcon)
                    }
                    // app名称
                    adBaseViewHolder.mAppName.text = ad.appName
                    // 广告描述
                    adBaseViewHolder.mAppDesc.text = ad.adDescription
                    // 广告转化文案
                    adBaseViewHolder.mAppDownloadBtn.text = ad.actionDescription
                    // 下载类型的可以设置下载监听
                    bindDownloadListener(adBaseViewHolder, ad)
                    adBaseViewHolder.mAppContainer.visibility = View.VISIBLE
                    adBaseViewHolder.mH5Container.visibility = View.GONE
                }
            }

            // 不喜欢
            adBaseViewHolder.mDislikeBtn.setOnClickListener { }
        }

        private fun bindDownloadListener(
            adBaseViewHolder: AdBaseViewHolder,
            ad: KsNativeAd?
        ) {
            val ksAppDownloadListener: KsAppDownloadListener = object : KsAppDownloadListener {
                override fun onIdle() {
                    adBaseViewHolder.mAppDownloadBtn.text = ad!!.actionDescription
                }

                override fun onDownloadStarted() {

                }

                override fun onProgressUpdate(progress: Int) {
                    adBaseViewHolder.mAppDownloadBtn.text = String.format(
                        "%s/100",
                        progress
                    )
                }

                override fun onDownloadFinished() {
                    adBaseViewHolder.mAppDownloadBtn.text = "立即安装"
                }

                override fun onDownloadFailed() {
                    adBaseViewHolder.mAppDownloadBtn.text = ad!!.actionDescription
                }

                override fun onInstalled() {
                    adBaseViewHolder.mAppDownloadBtn.text = "立即打开"
                }
            }
            // 注册下载监听器
            ad!!.setDownloadListener(ksAppDownloadListener)
        }

        //=============================================预加载===========================================
        fun loadCacheRewardAd(
            activity: Activity,
            entity: NewsEntity,
            callback: ZXADCallback
        ) {
            val scene = KsScene.Builder(
                Objects.requireNonNull(entity?.codeId).toLong()
            ).build() // 此为测试posId，请联系快手平台申请正式posId
            if (activity != null) {
                activity?.runOnUiThread {
                    KsAdSDK.getLoadManager()
                        .loadRewardVideoAd(scene, object : KsLoadManager.RewardVideoAdListener {
                            override fun onError(code: Int, msg: String) {
                                callback.onAdFail()
                                onEventPullFail(entity, AdEventUtils.AD_MODEL_REWARD)
                                AdEventUtils.onEvent(entity,code,msg)
                                LogUtils.d(
                                    TAG,
                                    "${entity?.adPlatform},errorMsg:${msg},errorCode:${code}"
                                )
                            }

                            override fun onRewardVideoAdLoad(adList: List<KsRewardVideoAd>?) {
                                if (adList != null && adList.size > 0) {
                                    callback.onAdSuccess()
                                    setRewardVideo(entity?.codeId, adList[0])
                                    onEventPullSuccess(entity, AdEventUtils.AD_MODEL_REWARD)
                                } else {
                                    callback.onAdFail()
                                }
                            }
                        })
                }
            }

        }

        fun playCacheRewardAd(
            activity: Activity,
            newsEntity: NewsEntity,
            listener: ZXADVideoListener,
            callback: ZXADCallback
        ) {
            entity = newsEntity
            val ksCacheRewardAd =
                getRewardVideo(newsEntity?.codeId)
            if (ksCacheRewardAd != null && ksCacheRewardAd.isAdEnable) {
                ksCacheRewardAd.setRewardAdInteractionListener(object :
                    KsRewardVideoAd.RewardAdInteractionListener {
                    override fun onAdClicked() {
                        listener.onAdVideoBarClick()
                        if (entity != null) {
                            onEventClick(entity!!, AdEventUtils.AD_MODEL_REWARD)
                        }
                    }

                    override fun onPageDismiss() {
                        listener.onAdClose(AdInfo(entity?.codeId))
                    }

                    override fun onVideoPlayError(
                        i: Int,
                        i1: Int
                    ) {
                        if (entity != null) {
                            onEventShowFail(entity!!, AdEventUtils.AD_MODEL_REWARD)
                        }
                        listener.onError("KS i:" + i + "i1:" + i1)
                        callback.onAdFail()
                    }

                    override fun onVideoPlayEnd() {
                        AdEventUtils.onEventComplete(entity!!, AdEventUtils.AD_MODEL_REWARD)
                    }

                    override fun onVideoPlayStart() {
                        if (entity != null) {
                            onEventShow(entity!!)
                        }
                        listener.onAdShow()
                        callback.onAdSuccess()
                    }

                    override fun onRewardVerify() {
                        listener.onSuccess()
                    }
                })
                ksCacheRewardAd.showRewardVideoAd(activity, null)
            } else {
                callback.onAdFail()
            }
        }

        private val mKsAdCacheMap =
            HashMap<String, ConcurrentLinkedQueue<KsRewardVideoAd>>()
        private val mKsFeedAdCacheMap: ArrayList<KsNativeAd?>? =
            ArrayList()

        private fun setRewardVideo(
            codeId: String,
            ksRewardAD: KsRewardVideoAd
        ) {
            if (mKsAdCacheMap[codeId] != null) {
                var ksRewardVideoAds =
                    mKsAdCacheMap[codeId]
                if (ksRewardVideoAds == null) {
                    ksRewardVideoAds = ConcurrentLinkedQueue()
                }
                ksRewardVideoAds.offer(ksRewardAD)
                mKsAdCacheMap[codeId] = ksRewardVideoAds
            } else {
                val concurrentLinkedQueue =
                    ConcurrentLinkedQueue<KsRewardVideoAd>()
                concurrentLinkedQueue.offer(ksRewardAD)
                mKsAdCacheMap[codeId] = concurrentLinkedQueue
            }
        }

        private fun getRewardVideo(
            codeId: String
        ): KsRewardVideoAd? {
            if (mKsAdCacheMap[codeId] != null) {
                val ksRewardVideoAds =
                    mKsAdCacheMap[codeId]
                if (ksRewardVideoAds != null && ksRewardVideoAds.size > 0) {
                    LogUtils.d("MingZhong", "播放快手$codeId")
                    return ksRewardVideoAds.poll()
                }
            }
            LogUtils.d("MingZhong", "播放快手失败$codeId")
            return null
        }

        fun cleanRewardCache() {
            mKsAdCacheMap.clear()
        }
    }
}